From: Toni Nikkanen Date: Wed, 11 Mar 2009 16:21:53 +0000 (+0200) Subject: Merge branch 'master' of https://git.maemo.org/projects/erwise X-Git-Url: http://git.maemo.org/git/?p=erwise;a=commitdiff_plain;h=HEAD;hp=14f784e8188aabcad35953e5ae2ff0ad63a35454 Merge branch 'master' of https://git.maemo.org/projects/erwise --- diff --git a/Cl/Cl.c b/Cl/Cl.c new file mode 100644 index 0000000..77b80ce --- /dev/null +++ b/Cl/Cl.c @@ -0,0 +1,413 @@ +/* + * Cl.c -- + * + * Author: Teemu Rantanen + * 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 + +#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 @#$#$ */ + } + + 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 index 0000000..f502d13 --- /dev/null +++ b/Cl/Cl.h @@ -0,0 +1,180 @@ +/* + * Cl.h -- + * + * Author: Teemu Rantanen + * 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 index 0000000..12e2688 --- /dev/null +++ b/Cl/ClConnection.c @@ -0,0 +1,324 @@ +/* + * ClConnection.c -- + * + * Author: Teemu Rantanen + * 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 +#include +#include + +#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 index 0000000..7b859c7 --- /dev/null +++ b/Cl/ClFTP.c @@ -0,0 +1,496 @@ +/* + * ClFTP.c -- + * + * Author: Teemu Rantanen + * 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 +#include +#include + +#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 index 0000000..15c0dfe --- /dev/null +++ b/Cl/ClHTTP.c @@ -0,0 +1,166 @@ +/* + * ClHTTP.c -- + * + * Author: Teemu Rantanen + * 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 +#include +#include +#include + +#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 index 0000000..932131f --- /dev/null +++ b/Cl/ClMisc.c @@ -0,0 +1,38 @@ +/* + * ClMisc.c -- + * + * Author: Teemu Rantanen + * 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 index 0000000..9379405 --- /dev/null +++ b/Cl/Imakefile @@ -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 index 0000000..631a7de --- /dev/null +++ b/Cl/Makefile @@ -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 +# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $ +# +# Platform-specific parameters may be set in the appropriate .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 index 0000000..3f7af2c --- /dev/null +++ b/Cl/WWWLibrary/HTAccess.c @@ -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 +#include + +#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 index 0000000..ecbc165 --- /dev/null +++ b/Cl/WWWLibrary/HTAccess.h @@ -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 index 0000000..d5a0053 --- /dev/null +++ b/Cl/WWWLibrary/HTAnchor.c @@ -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 +#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 index 0000000..63f2f97 --- /dev/null +++ b/Cl/WWWLibrary/HTAnchor.h @@ -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 index 0000000..44a099f --- /dev/null +++ b/Cl/WWWLibrary/HTAtom.c @@ -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 +#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; inext) { + 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 index 0000000..2ebef26 --- /dev/null +++ b/Cl/WWWLibrary/HTAtom.h @@ -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 index 0000000..781015e --- /dev/null +++ b/Cl/WWWLibrary/HTBrowse.h @@ -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 index 0000000..320ab9b --- /dev/null +++ b/Cl/WWWLibrary/HTChunk.c @@ -0,0 +1,84 @@ +/* Chunk handling: Flexible arrays +** =============================== +** +*/ + +#include "HTUtils.h" +#include "HTChunk.h" +#include +/* 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 index 0000000..a1da188 --- /dev/null +++ b/Cl/WWWLibrary/HTChunk.h @@ -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 index 0000000..7280bb4 --- /dev/null +++ b/Cl/WWWLibrary/HTFTP.c @@ -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 ... +** +** 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 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 index 0000000..bd0ffcd --- /dev/null +++ b/Cl/WWWLibrary/HTFTP.h @@ -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 index 0000000..3bef015 --- /dev/null +++ b/Cl/WWWLibrary/HTFile.c @@ -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 +#include +#include +#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=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 index 0000000..473275a --- /dev/null +++ b/Cl/WWWLibrary/HTFile.h @@ -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 index 0000000..914d33e --- /dev/null +++ b/Cl/WWWLibrary/HTFont.h @@ -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 index 0000000..ab2a9dd --- /dev/null +++ b/Cl/WWWLibrary/HTFormat.c @@ -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 index 0000000..70d3fee --- /dev/null +++ b/Cl/WWWLibrary/HTFormat.h @@ -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 index 0000000..5ef66ca --- /dev/null +++ b/Cl/WWWLibrary/HTGopher.c @@ -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 +#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 +#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 index 0000000..83abf2e --- /dev/null +++ b/Cl/WWWLibrary/HTGopher.h @@ -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 index 0000000..ca5bcb0 --- /dev/null +++ b/Cl/WWWLibrary/HTHistory.c @@ -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 index 0000000..bb1bab0 --- /dev/null +++ b/Cl/WWWLibrary/HTHistory.h @@ -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 index 0000000..7d40f3e --- /dev/null +++ b/Cl/WWWLibrary/HTList.c @@ -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 +#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 index 0000000..4aed995 --- /dev/null +++ b/Cl/WWWLibrary/HTList.h @@ -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 index 0000000..ec1471d --- /dev/null +++ b/Cl/WWWLibrary/HTML.c @@ -0,0 +1,429 @@ +/* HTML Parser +** =========== +*/ +#include +#include + +#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 index 0000000..acbe240 --- /dev/null +++ b/Cl/WWWLibrary/HTML.h @@ -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 index 0000000..94b827d --- /dev/null +++ b/Cl/WWWLibrary/HTNews.c @@ -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 +#include "HTUtils.h" /* Coding convention macros */ +#include "tcp.h" + +#include "HTNews.h" + +#include "HText.h" +#include "HTParse.h" +#include "HTFormat.h" + +#ifdef NeXTStep +#include +#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 " +** 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 */ + } + 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 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 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 index 0000000..2883464 --- /dev/null +++ b/Cl/WWWLibrary/HTNews.h @@ -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 index 0000000..09b8aa0 --- /dev/null +++ b/Cl/WWWLibrary/HTParse.c @@ -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 index 0000000..0bd6d92 --- /dev/null +++ b/Cl/WWWLibrary/HTParse.h @@ -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 index 0000000..e997423 --- /dev/null +++ b/Cl/WWWLibrary/HTString.c @@ -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 +#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 index 0000000..1b3c6f2 --- /dev/null +++ b/Cl/WWWLibrary/HTString.h @@ -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 index 0000000..b15801c --- /dev/null +++ b/Cl/WWWLibrary/HTStyle.c @@ -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; istyles; 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 index 0000000..cfcc788 --- /dev/null +++ b/Cl/WWWLibrary/HTStyle.h @@ -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 +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 index 0000000..afa1727 --- /dev/null +++ b/Cl/WWWLibrary/HTTCP.c @@ -0,0 +1,297 @@ +/* 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 +/* Toni */ +/* extern char *sys_errlist[]; */ +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: */ + printf("HTTCP: Calling gethostbyname2(\"%s\",AF_INET)\n", host); + phost=gethostbyname2(host,AF_INET); /* See netdb.h */ + if (!phost) { + printf( + "HTTPAccess: Can't find internet node name `%s', h_errno: %d.\n",host,h_errno); + 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) { + 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 index 0000000..3e9a04a --- /dev/null +++ b/Cl/WWWLibrary/HTTCP.h @@ -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 index 0000000..69c6006 --- /dev/null +++ b/Cl/WWWLibrary/HTTP.c @@ -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 index 0000000..be72957 --- /dev/null +++ b/Cl/WWWLibrary/HTTP.h @@ -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 index 0000000..7d92c1d --- /dev/null +++ b/Cl/WWWLibrary/HTUtils.h @@ -0,0 +1,192 @@ +/* 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 +#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 /* NeXT */ +#endif +#ifndef MACH /* Vincent.Cate@furmint.nectar.cs.cmu.edu */ +#include /* ANSI */ +#endif +#else +#include /* ultrix */ +#include +#include +#endif + +#else /* VMS */ +#include +#include +#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 80 /* 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 +/* Toni */ +#include +#endif /* ERWISE */ + +#ifdef CURSES +/* htbrowse.c; */ +#include + +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 index 0000000..c060180 --- /dev/null +++ b/Cl/WWWLibrary/HText.h @@ -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 index 0000000..7b02026 --- /dev/null +++ b/Cl/WWWLibrary/Imakefile @@ -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 index 0000000..05a4ccd --- /dev/null +++ b/Cl/WWWLibrary/Makefile @@ -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 +# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $ +# +# Platform-specific parameters may be set in the appropriate .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/README b/Cl/WWWLibrary/README new file mode 100644 index 0000000..5e3aa6b --- /dev/null +++ b/Cl/WWWLibrary/README @@ -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 index 0000000..ede5fd9 --- /dev/null +++ b/Cl/WWWLibrary/SGML.c @@ -0,0 +1,426 @@ +/* General SGML Parser code SGML.c +** ======================== +*/ +#include +#include +#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 \n", old_tag->name); + if (!old_tag->end) { + if (TRACE) fprintf(stderr,"SGML: Illegal end tag 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 when expecting . assumed.\n", + old_tag->name, t->name, t->name); + } else { /* last level */ + if (TRACE) fprintf(stderr, + "SGML: Found when expecting . 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 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; isize; 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 (TRACE) fprintf(stderr,"SGML: `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 \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 index 0000000..a1bd043 --- /dev/null +++ b/Cl/WWWLibrary/SGML.h @@ -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 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 index 0000000..246cd83 --- /dev/null +++ b/Cl/WWWLibrary/WWW.h @@ -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 index 0000000..969e9c8 --- /dev/null +++ b/Cl/WWWLibrary/tcp.h @@ -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, +** EvA Eelco van Asperen +** +** 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 /* NeXT has all this packaged up */ +#define ntohs(x) (x) +#define htons(x) (x) +#include /* Get ECONNRESET etc */ +#define SELECT /* Is supported ok */ +#define INCLUDES_DONE + +#else /* Not NeXT */ +#ifndef STDIO_H +#include +#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 /* 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 +#include +#include +#include +#include +#include +#include +#include /* independent */ +extern char asciitoebcdic[], ebcdictoascii[]; +#define TOASCII(c) (c=='\n' ? 10 : ebcdictoascii[c]) +#define FROMASCII(c) (c== 10 ? '\n' : asciitoebcdic[c]) +#include +#include +#include +#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 +*/ + +#ifdef PCNFS +#include +#include +#ifndef STDIO_H +#include +#define STDIO_H +#endif + +#include /* independent */ +#include /* independent */ +#include +#include /* 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 +/* #include not ultrix */ +#include +#ifndef STDIO_H +#include +#define STDIO_H +#endif + +#include /* independent */ +#include /* independent */ +#include +#include +#include /* For open() etc */ +#define INCLUDES_DONE +#endif /* Normal includes */ + + +/* Default include files for TCP +*/ +#ifndef TCP_INCLUDES_DONE +#include +#include +#include /* Must be after netinet/in.h */ +#include +#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 index 0000000..5a251f6 --- /dev/null +++ b/HText/DefaultStyles.c @@ -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 index 0000000..c9f4a5a --- /dev/null +++ b/HText/HText.c @@ -0,0 +1,797 @@ +/* + * HText.c -- + * + * Author: Teemu Rantanen + * 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 + +#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 index 0000000..a96082b --- /dev/null +++ b/HText/HText.h @@ -0,0 +1,159 @@ +/* + * HText.h -- + * + * Author: Teemu Rantanen + * 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 index 0000000..8622d9a --- /dev/null +++ b/HText/Imakefile @@ -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 index 0000000..d480967 --- /dev/null +++ b/HText/Makefile @@ -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 +# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $ +# +# Platform-specific parameters may be set in the appropriate .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 index 0000000..0f5a3c7 --- /dev/null +++ b/HText/dummy.c @@ -0,0 +1,27 @@ +/* + * dummy.c -- + * + * Author: Teemu Rantanen + * 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 +#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 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 index 0000000..d81248c --- /dev/null +++ b/Makefile @@ -0,0 +1,1266 @@ +# Makefile generated by imake - do not edit! +# $Xorg: imake.c,v 1.6 2001/02/09 02:03:15 xorgcvs Exp $ + +# ---------------------------------------------------------------------- +# Makefile generated from "Imake.tmpl" and +# $Xorg: Imake.tmpl,v 1.4 2000/08/17 19:41:46 cpqbld Exp $ +# $XdotOrg: util/cf/Imake.tmpl,v 1.17 2006/04/15 15:55:25 herrb Exp $ +# +# +# +# +# $XFree86: xc/config/cf/Imake.tmpl,v 3.155 2003/12/24 18:58:41 dickey Exp $ +# ---------------------------------------------------------------------- + +all:: + +.SUFFIXES: .i + +# $XdotOrg: util/cf/Imake.cf,v 1.12 2005/11/08 06:33:24 jkj Exp $ +# $Xorg: Imake.cf,v 1.4 2000/08/17 19:41:45 cpqbld Exp $ + +# $XFree86: xc/config/cf/Imake.cf,v 3.88 2003/12/16 21:30:21 herrb Exp $ + +# ----------------------------------------------------------------------- +# site-specific configuration parameters that need to come before +# the platform-specific parameters - edit site.def to change + +# site: $TOG: site.sample /main/r64_final/1 1998/02/05 16:28:49 kaleb $ + +# site: $XFree86: xc/config/cf/site.def,v 3.24 2000/06/25 20:17:29 dawes Exp $ + +# $XFree86: xc/config/cf/xf86site.def,v 3.186 2003/06/25 18:06:22 eich Exp $ + +# ---------------------------------------------------------------------- +# platform-specific configuration parameters - edit linux.cf to change + +# $XdotOrg: util/cf/linux.cf,v 1.31 2005/10/21 19:10:27 ajax Exp $ +# platform: $Xorg: linux.cf,v 1.3 2000/08/17 19:41:47 cpqbld Exp $ + +# platform: $XFree86: xc/config/cf/linux.cf,v 3.220 2003/12/30 22:38:33 tsi Exp $ + +# operating system: Linux 2.6.28-8-generic armv5tel [ELF] (2.6.28) +# libc: (6.5.0) +# binutils: (216) + +# $Xorg: lnxLib.rules,v 1.3 2000/08/17 19:41:47 cpqbld Exp $ +# $XFree86: xc/config/cf/lnxLib.rules,v 3.52 2003/10/31 20:49:03 herrb Exp $ + +# $XdotOrg: util/cf/xorg.cf,v 1.53 2005/10/03 16:08:44 alanc Exp $ + +# $Xorg: xfree86.cf,v 1.4 2000/08/17 19:41:49 cpqbld Exp $ + +XORG_VERSION_CURRENT = (((6) * 10000000) + ((9) * 100000) + ((0) * 1000) + 0) +RELEASE_VERSION = RELEASE-1 + +DRIVERSDKDIR = $(USRLIBDIR)/Server +DRIVERSDKMODULEDIR = $(USRLIBDIR)/Server/modules +DRIVERSDKINCLUDEDIR = $(USRLIBDIR)/Server/include + + XF86SRC = $(SERVERSRC)/hw/xfree86 + XF86COMSRC = $(XF86SRC)/common + XF86PARSERSRC = $(XF86SRC)/parser + XF86OSSRC = $(XF86SRC)/os-support + XF86DRIVERSRC = $(XF86SRC)/drivers + DRIVERSRC = $(XF86DRIVERSRC) + + XFREE86DOCDIR = $(DOCDIR) + XFREE86PSDOCDIR = $(DOCPSDIR) + XFREE86PDFDOCDIR = $(DOCPDFDIR) + XFREE86HTMLDOCDIR = $(DOCHTMLDIR) +XFREE86JAPANESEDOCDIR = $(DOCDIR)/Japanese + +# $Xorg: xf86.rules,v 1.3 2000/08/17 19:41:48 cpqbld Exp $ + +# $XFree86: xc/config/cf/xf86.rules,v 3.34tsi Exp $ + + SELINUX_LDFLAGS = + + SELINUX_INCLUDES = -I/usr/include/selinux + + SELINUX_CFLAGS = -DHAVE_SELINUX + + SELINUX_LIBS = -lselinux + +# ---------------------------------------------------------------------- +# site-specific configuration parameters that go after +# the platform-specific parameters - edit site.def to change + +# site: $TOG: site.sample /main/r64_final/1 1998/02/05 16:28:49 kaleb $ + +# site: $XFree86: xc/config/cf/site.def,v 3.24 2000/06/25 20:17:29 dawes Exp $ + +# --------------------------------------------------------------------- +# Imake rules for building libraries, programs, scripts, and data files +# rules: $Xorg: Imake.rules,v 1.3 2000/08/17 19:41:46 cpqbld Exp $ +# rules: $XdotOrg: util/cf/Imake.rules,v 1.11 2005/11/08 06:33:24 jkj Exp $ +# +# +# +# +# rules: $XFree86: xc/config/cf/Imake.rules,v 3.128 2003/11/15 03:25:17 dawes Exp $ + +.PHONY: all interfaces install install.man install.lib install.sdk depend includes cleandir + + _NULLCMD_ = @ echo -n + +X_BYTE_ORDER = X_LITTLE_ENDIAN + +GLIDE2INCDIR = + +GLIDE3INCDIR = + +GLIDE3LIBNAME = + +TKLIBNAME = tk8.4 + +TKLIBDIR = /usr/lib + +TCLLIBNAME = tcl8.4 + +TCLIBDIR = /usr/lib + + PATHSEP = / + SHELL = /bin/sh -e + + TOP = . + CURRENT_DIR = . + + IMAKE = imake + DEPEND = gccmakedep + MKDIRHIER = mkdir -p + REVPATH = revpath + EXPORTLISTGEN = + RMAN = /usr/bin/rman + RMANBASENAME = rman + RMANOPTIONS = + CONFIGSRC = $(TOP)/config + IMAKESRC = $(CONFIGSRC)/imake + DEPENDSRC = $(CONFIGSRC)/util + + INCROOT = /usr/include + USRLIBDIR = /usr/lib + VARDIR = /var + VARLIBDIR = $(VARDIR)/lib + SYSTEMUSRLIBDIR = /usr/lib + SYSTEMUSRINCDIR = /usr/include + SHLIBDIR = /usr/lib + LINTLIBDIR = $(USRLIBDIR)/lint + MANPATH = /usr/share/man + MANSOURCEPATH = $(MANPATH)/man + MANDIR = $(MANSOURCEPATH)$(MANSECT) + SYSCALLMANDIR = $(MANSOURCEPATH)$(SYSCALLMANSECT) + LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSECT) + DRIVERMANDIR = $(MANSOURCEPATH)4 + FILEMANDIR = $(MANSOURCEPATH)$(FILEMANSECT) + GAMEMANDIR = $(MANSOURCEPATH)$(GAMEMANSECT) + MISCMANDIR = $(MANSOURCEPATH)7 + ADMMANDIR = $(MANSOURCEPATH)$(ADMMANSECT) + ICONDIR = "/usr/share/icons" + XCURSORPATH = "~/.icons:/usr/share/icons:/usr/share/pixmaps" + DRIVERMANDIR = $(MANSOURCEPATH)4 + LOGDIRECTORY = $(VARDIR)/log + + VARRUNDIR = $(VARDIR)/run + + VARDBDIR = $(VARDIR)/lib + + AR = ar clq + +# Nice try but useless: make will inherit BOOTSTRAPCFLAGS +# from top Makefile + BOOTSTRAPCFLAGS = + + CC = gcc + AS = gcc -c -x assembler + +.SUFFIXES: .cc + + CXX = c++ + + CXXFILT = c++filt + + CXXLIB = -lstdc++ + + CXXDEBUGFLAGS = -g -O2 -fno-strict-aliasing +CXXDEPENDINCLUDES = + CXXEXTRA_DEFINES = +CXXEXTRA_INCLUDES = + CXXSTD_DEFINES = -Dlinux -D__arm__ -D__arm32__ -U__arm -Uarm -D_POSIX_C_SOURCE=199309L -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $(CXXPROJECT_DEFINES) + CXXOPTIONS = + CXXINCLUDES = $(INCLUDES) $(TOP_INCLUDES) $(CXXEXTRA_INCLUDES) + CXXDEFINES = $(CXXINCLUDES) $(CXXSTD_DEFINES) $(THREADS_CXXDEFINES) $(DEFINES) $(CXXEXTRA_DEFINES) + CXXFLAGS = $(CXXDEBUGFLAGS) $(CXXOPTIONS) $(THREADS_CXXFLAGS) $(CXXDEFINES) + + COMPRESS = compress + GZIPCMD = gzip + + CPP = cpp $(STD_CPP_DEFINES) + RAWCPP = cpp -undef $(STD_CPP_OPTIONS) + PREPROCESSCMD = gcc -E $(STD_CPP_DEFINES) + + INSTALL = install + INSTALLFLAGS = -c + + LD = gcc -nostdlib + + LEX = flex -l + M4 = m4 + M4FLAGS = + LEXLIB = -lfl + YACC = bison -y + CCYACC = bison -y + + LINT = lint + + LINTLIBFLAG = -C + LINTOPTS = -axz + LN = ln -s + MAKE = make + MV = mv -f + CP = cp + + RANLIB = ranlib + + RANLIBINSTFLAGS = + + RM = rm -f + PERL = perl + PERLOPTS = + PERLENVSETUP = env LC_ALL=C + + MANSECT = 1 + SYSCALLMANSECT = 2 + LIBMANSECT = 3 + DRIVERMANSECT = 4 + FILEMANSECT = 5 + GAMEMANSECT = 6 + MISCMANSECT = 7 + ADMMANSECT = 8 + MANSRCSECT = s + MANNEWSECT = n + PROJECTMANSUFFIX = x + MANSUFFIX = $(MANSECT)$(PROJECTMANSUFFIX) + SYSCALLMANSUFFIX = $(SYSCALLMANSECT)$(PROJECTMANSUFFIX) + LIBMANSUFFIX = $(LIBMANSECT)$(PROJECTMANSUFFIX) + DRIVERMANSUFFIX = 4x + FILEMANSUFFIX = $(FILEMANSECT)$(PROJECTMANSUFFIX) + GAMEMANSUFFIX = $(GAMEMANSECT)$(PROJECTMANSUFFIX) + MISCMANSUFFIX = 7x + ADMMANSUFFIX = $(ADMMANSECT)$(PROJECTMANSUFFIX) + ADMINMANSUFFIX = 8 + MANSRCSUFFIX = man + MANNEWSUFFIX = _man + MANDEFS = -D__apploaddir__=$(XAPPLOADDIR) -D__filemansuffix__=$(FILEMANSECT)$(PROJECTMANSUFFIX) -D__osfilemansuffix__=$(FILEMANSECT) -D__libmansuffix__=$(LIBMANSECT)$(PROJECTMANSUFFIX) -D__oslibmansuffix__=$(LIBMANSECT) -D__mansuffix__=$(MANSECT)$(PROJECTMANSUFFIX) -D__osmansuffix__=$(MANSECT) -D__syscallmansuffix__=$(SYSCALLMANSECT)$(PROJECTMANSUFFIX) -D__ossysmansuffix__=$(SYSCALLMANSECT) -D__gamemansuffix__=$(GAMEMANSECT)$(PROJECTMANSUFFIX) -D__osgamemansuffix__=$(GAMEMANSECT) -D__miscmansuffix__=$(MISCMANSECT)$(PROJECTMANSUFFIX) -D__osmiscmansuffix__=$(MISCMANSECT) -D__admmansuffix__=$(ADMMANSECT)$(PROJECTMANSUFFIX) -D__osadmmansuffix__=$(ADMMANSECT) -D__miscmansuffix__=$(MISCMANSECT)$(PROJECTMANSUFFIX) -D__osmiscmansuffix__=$(MISCMANSECT) -D__drivermansuffix__=$(DRIVERMANSECT)$(PROJECTMANSUFFIX) -D__osdrivermansuffix__=$(DRIVERMANSECT) -D__adminmansuffix__=$(ADMINMANSUFFIX) -D__projectroot__=$(PROJECTROOT) -D__xconfigfile__=$(XCONFIGFILE) -D__xconfigdir__=$(XCONFIGDIR) -D__xlogfile__=$(XLOGFILE) -D__xservername__=$(XSERVERNAME) -D__appmansuffix__=$(MANSECT)$(PROJECTMANSUFFIX) $(XORGMANDEFS) $(VENDORMANDEFS) + + COMPRESSMANCMD = gzip -n + + TROFF = groff -Tps + NROFF = nroff + + MSMACROS = -ms + MANMACROS = -man + TBL = tbl + EQN = eqn + NEQN = neqn + COL = col + COLFLAGS = -b + + MODCC = gcc + + MODCPP = cpp + MODCFLAGS = $(CFLAGS) + MODAS = gcc -c -x assembler + MODASFLAGS = + + MODLD = gcc -nostdlib + + MODLDFLAGS = +MODLDCOMBINEFLAGS = -r + MODAR = ar clq + + MODRANLIB = ranlib + + DVIPS = dvips + LATEX = latex + + STD_INCLUDES = + STD_CPP_OPTIONS = -traditional + STD_CPP_DEFINES = -traditional -Dlinux -D__arm__ -D__arm32__ -U__arm -Uarm -D_POSIX_C_SOURCE=199309L -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $(PROJECT_DEFINES) + STD_DEFINES = -Dlinux -D__arm__ -D__arm32__ -U__arm -Uarm -D_POSIX_C_SOURCE=199309L -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $(PROJECT_DEFINES) + EXTRA_LOAD_FLAGS = + EXTRA_LDOPTIONS = + EXTRA_LIBRARIES = + TAGS = ctags + + PARALLELMFLAGS = + + SHAREDCODEDEF = + SHLIBDEF = + + SHLIBLDFLAGS = -shared $(SHLIBGLOBALSFLAGS) + + NOSTDLIB = -nostdlib + POSTNOSTDLIB = -Wl,-Bstatic -lgcc -Wl,-Bdynamic + + PICFLAGS = -fPIC + + CXXPICFLAGS = -fPIC + + PROTO_DEFINES = -DFUNCPROTO=15 -DNARROWPROTO + + INSTPGMFLAGS = + + INSTBINFLAGS = -m 0755 + INSTUIDFLAGS = -m 4711 + INSTLIBFLAGS = -m 0644 + INSTINCFLAGS = -m 0444 + INSTMANFLAGS = -m 0444 + INSTDATFLAGS = -m 0444 + INSTKMEMFLAGS = -m 4711 + + PROJECTROOT = /usr + + CDEBUGFLAGS = -g -O2 -fno-strict-aliasing + CCOPTIONS = + + ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(INSTALLED_INCLUDES) $(STD_INCLUDES) + ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(THREADS_DEFINES) $(MODULE_DEFINES) $(DEFINES) $(EXTRA_DEFINES) + CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(THREADS_CFLAGS) $(MODULE_CFLAGS) $(ALLDEFINES) + LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES) $(DEPEND_DEFINES) + LDPRELIB = $(INSTALLED_LIBS) + LDPOSTLIB = + LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(EXTRA_LDOPTIONS) $(THREADS_LDFLAGS) $(LOCAL_LDFLAGS) $(LDPRELIBS) + CXXLDOPTIONS = $(CXXDEBUGFLAGS) $(CXXOPTIONS) $(EXTRA_LDOPTIONS) $(THREADS_CXXLDFLAGS) $(LOCAL_LDFLAGS) $(LDPRELIBS) + + LDLIBS = $(LDPOSTLIBS) $(THREADS_LIBS) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + + CCLINK = $(CC) + + CXXLINK = $(CXX) + + LDSTRIPFLAGS = -x + LDCOMBINEFLAGS = -r + DEPENDFLAGS = + DEPEND_DEFINES = + +# Not sure this belongs here + TKLIBDIR = /usr/lib + TKINCDIR = /usr/include + TKLIBNAME = tk8.4 + TKLIBRARY = -L$(TKLIBDIR) -l$(TKLIBNAME) + TCLLIBDIR = /usr/lib + TCLINCDIR = /usr/include + TCLLIBNAME = tcl8.4 + TCLLIBRARY = -L$(TCLLIBDIR) -l$(TCLLIBNAME) + + MACROFILE = linux.cf + RM_CMD = $(RM) + + IMAKE_DEFINES = + IMAKE_WARNINGS = -Wundef + + IRULESRC = $(CONFIGDIR) + IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES) $(IMAKE_WARNINGS) + + ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/X11.tmpl $(IRULESRC)/site.def $(IRULESRC)/$(MACROFILE) $(IRULESRC)/xfree86.cf $(IRULESRC)/xf86.rules $(IRULESRC)/xorgsite.def $(IRULESRC)/host.def $(EXTRA_ICONFIGFILES) + +# $Xorg: X11.rules,v 1.4 2000/08/17 19:41:46 cpqbld Exp $ + +# $XFree86: xc/config/cf/X11.rules,v 1.6 2001/01/17 16:22:31 dawes Exp $ + +# ---------------------------------------------------------------------- +# X Window System Build Parameters and Rules +# $XdotOrg: util/cf/X11.tmpl,v 1.54 2006/04/15 15:55:25 herrb Exp $ +# $Xorg: X11.tmpl,v 1.6 2000/08/17 19:41:46 cpqbld Exp $ +# +# +# +# +# $XFree86: xc/config/cf/X11.tmpl,v 1.248 2004/02/16 04:07:37 dawes Exp $ + +XORGRELSTRING = `echo 6 9 0 | sed -e 's/ /./g' -e 's/^/Version\\\ /'` + XORGMANNAME = X Version 11 + +STICKY_DEFINES = -DHAS_STICKY_DIR_BIT + +FCHOWN_DEFINES = -DHAS_FCHOWN + +# ----------------------------------------------------------------------- +# X Window System make variables; these need to be coordinated with rules + + XTOP = $(TOP) + BINDIR = /usr/bin + BUILDINCROOT = $(TOP)/exports + BUILDINCDIR = $(BUILDINCROOT)/include + BUILDINCTOP = ../.. + BUILDLIBDIR = $(TOP)/exports/lib + BUILDLIBTOP = ../.. + BUILDBINDIR = $(TOP)/exports/bin + BUILDBINTOP = ../.. + BUILDMODULEDIR = $(BUILDLIBDIR)/modules + BUILDI18NDIR = $(BUILDLIBDIR)/locale + BUILDMODULETOP = $(BUILDLIBTOP)/.. + XBUILDINCROOT = $(XTOP)/exports + XBUILDINCDIR = $(XBUILDINCROOT)/include/X11 + XBUILDINCTOP = ../../.. + XBUILDBINDIR = $(XBUILDINCROOT)/bin + INCDIR = $(INCROOT) + ADMDIR = /usr/adm + LIBDIR = /usr/lib/X11 + SHAREDIR = /usr/share/X11 + LIBEXECDIR = /usr/libexec + MODULEDIR = $(USRLIBDIR)/modules + TOP_X_INCLUDES = + XBINDIR = $(PROJECTROOT)/bin + + INSTSRCDIR = /usr/src + + ETCX11DIR = /etc/X11 + + CONFDIR = $(ETCX11DIR) + + DOCDIR = $(LIBDIR)/doc + DOCHTMLDIR = $(DOCDIR)/html + DOCPSDIR = $(DOCDIR)/PostScript + DOCPDFDIR = $(DOCDIR)/PDF + FONTDIR = /usr/share/fonts/X11 + ENCODINGSDIR = /usr/share/fonts/X11/encodings + XINITDIR = $(LIBDIR)/xinit + XDMDIR = $(LIBDIR)/xdm + XDMVARDIR = $(VARLIBDIR)/xdm + TWMDIR = $(LIBDIR)/twm + XSMDIR = $(LIBDIR)/xsm + NLSDIR = $(LIBDIR)/nls + XLOCALEDIR = $(LIBDIR)/locale + LBXPROXYDIR = $(LIBDIR)/lbxproxy + PROXYMANAGERDIR = $(LIBDIR)/proxymngr + XPRINTDIR = $(LIBDIR)/xserver + XAPPLOADDIR = /etc/X11/app-defaults + FONTCFLAGS = -t + + INSTAPPFLAGS = $(INSTDATFLAGS) + + RGB = $(XBINDIR)/rgb + FONTC = $(XBINDIR)/bdftopcf + MKFONTSCALE = $(XBINDIR)/mkfontscale + MKFONTDIR = $(XBINDIR)/mkfontdir + MKHTMLINDEX = $(XBINDIR)/mkhtmlindex + UCS2ANY = $(XBINDIR)/ucs2any + BDFTRUNCATE = $(XBINDIR)/bdftruncate + UCSMAPPREFIX = $(FONTDIR)/util/map- + XCURSORGEN = $(XBINDIR)/xcursorgen + + HTMLINDEXCMD = HtmlIndexCmd + + DOCUTILSRC = $(XTOP)/doc/util + CLIENTSRC = $(TOP)/clients + DEMOSRC = $(TOP)/demos + XDOCMACROS = $(DOCUTILSRC)/macros.t + XIDXMACROS = $(DOCUTILSRC)/indexmacros.t + PROGRAMSRC = $(TOP)/programs + LIBSRC = $(XTOP)/lib + FONTSRC = $(XTOP)/fonts + ENCODINGSSRC = $(FONTSRC)/encodings + INCLUDESRC = $(BUILDINCROOT)/include + XINCLUDESRC = $(INCLUDESRC)/X11 + SERVERSRC = $(XTOP)/programs/Xserver + CONTRIBSRC = $(XTOP)/../contrib + UNSUPPORTEDSRC = $(XTOP)/unsupported + DOCSRC = $(XTOP)/doc + RGBSRC = $(XTOP)/programs/rgb + BDFTOPCFSRC = $(PROGRAMSRC)/bdftopcf + MKFONTDIRSRC = $(PROGRAMSRC)/mkfontdir + FONTSERVERSRC = $(PROGRAMSRC)/xfs + FONTINCSRC = $(XTOP)/include/fonts + EXTINCSRC = $(XTOP)/include/extensions + FTSOURCEDIR = FreeTypeSrcDir + DRMSRCDIR = $(TOP)/extras/drm + MESASRCDIR = $(TOP)/extras/Mesa + OGLSAMPLESRCDIR = $(TOP)/extras/ogl-sample + PSWRAPSRC = $(XTOP)/config/pswrap + TRANSCOMMSRC = $(LIBSRC)/xtrans + TRANS_INCLUDES = -I$(TRANSCOMMSRC) + CONNECTION_FLAGS = -DUNIXCONN -DTCPCONN $(STICKY_DEFINES) $(FCHOWN_DEFINES) -DIPv6 +XTRANS_FAILDEFINES = -DFAIL_HARD + + VENDORMANNAME = X.Org + VENDORMANVERSION = `echo 6 9 0 | sed -e 's/ /./g' -e 's/^/Version\\\ /'` + XORGMANDEFS = -D__xorgversion__="\"$(XORGRELSTRING)\" \"$(XORGMANNAME)\"" + VENDORMANDEFS = -D__vendorversion__="$(VENDORMANVERSION) $(VENDORMANNAME)" + VENDORNAME = The X.Org Foundation + VENDORNAMESHORT = X.Org + + VENDORWEBSUPPORT = http://wiki.X.Org + +VENDORSUPPORTDEFS = -D__VENDORDWEBSUPPORT__='"$(VENDORWEBSUPPORT)"' + + XKBDEFRULES = xorg + XKBDEFRULESDEFS = -D__XKBDEFRULES__='"$(XKBDEFRULES)"' + + XCONFIGFILE = xorg.conf + XCONFIGDIR = $(LIBDIR) + XLOGFILE = Xorg + XSERVERNAME = Xorg + + XENVLIBDIR = $(USRLIBDIR) + CLIENTENVSETUP = LD_LIBRARY_PATH=$(XENVLIBDIR) XLOCALEDIR=$(BUILDLIBDIR)/locale + +# $Xorg: lnxLib.tmpl,v 1.3 2000/08/17 19:41:47 cpqbld Exp $ +# $XFree86: xc/config/cf/lnxLib.tmpl,v 3.19 2003/10/15 22:47:48 herrb Exp $ + + XLIBSRC = $(LIBSRC)/X11 + +SOXLIBREV = 6.2 +DEPXONLYLIB = +XONLYLIB = -lX11 + +LINTXONLY = $(LINTLIBDIR)/llib-lX11.ln + + DEPXLIBONLY = $(DEPXONLYLIB) + XLIBONLY = $(XONLYLIB) + LINTXONLYLIB = $(LINTXONLY) + + XEXTLIBSRC = $(LIBSRC)/Xext + +SOXEXTREV = 6.4 +DEPEXTENSIONLIB = +EXTENSIONLIB = -lXext + +LINTEXTENSION = $(LINTLIBDIR)/llib-lXext.ln + +LINTEXTENSIONLIB = $(LINTEXTENSION) + DEPXLIB = $(DEPEXTENSIONLIB) $(DEPXONLYLIB) + XLIB = $(EXTENSIONLIB) $(XONLYLIB) + LINTXLIB = $(LINTXONLYLIB) + + XSSLIBSRC = $(LIBSRC)/Xss + +SOXSSREV = 1.0 +DEPXSSLIB = +XSSLIB = -lXss + +LINTXSS = $(LINTLIBDIR)/llib-lXss.ln + + XXF86MISCLIBSRC = $(LIBSRC)/Xxf86misc + +SOXXF86MISCREV = 1.1 +DEPXXF86MISCLIB = +XXF86MISCLIB = -lXxf86misc + +LINTXXF86MISC = $(LINTLIBDIR)/llib-lXxf86misc.ln + + XXF86VMLIBSRC = $(LIBSRC)/Xxf86vm + +SOXXF86VMREV = 1.0 +DEPXXF86VMLIB = +XXF86VMLIB = -lXxf86vm + +LINTXXF86VM = $(LINTLIBDIR)/llib-lXxf86vm.ln + + XXF86DGALIBSRC = $(LIBSRC)/Xxf86dga + +SOXXF86DGAREV = 1.0 +DEPXXF86DGALIB = +XXF86DGALIB = -lXxf86dga + +LINTXXF86DGA = $(LINTLIBDIR)/llib-lXxf86dga.ln + + XXF86RUSHLIBSRC = $(LIBSRC)/Xxf86rush + +SOXXF86RUSHREV = 1.0 +DEPXXF86RUSHLIB = +XXF86RUSHLIB = -lXxf86rush + +LINTXXF86RUSH = $(LINTLIBDIR)/llib-lXxf86rush.ln + + XVLIBSRC = $(LIBSRC)/Xv + +SOXVREV = 1.0 +DEPXVLIB = +XVLIB = -lXv + +LINTXV = $(LINTLIBDIR)/llib-lXv.ln + + XVMCLIBSRC = $(LIBSRC)/XvMC + +SOXVMCREV = 1.0 +DEPXVMCLIB = +XVMCLIB = -lXvMC + +LINTXVMC = $(LINTLIBDIR)/llib-lXvMC.ln + + XINERAMALIBSRC = $(LIBSRC)/Xinerama + +SOXINERAMAREV = 1.0 +DEPXINERAMALIB = +XINERAMALIB = -lXinerama + +LINTXINERAMA = $(LINTLIBDIR)/llib-lXinerama.ln + + XRESLIBSRC = $(LIBSRC)/XRes + +SOXRESREV = 1.0 +DEPXRESLIB = +XRESLIB = -lXRes + +LINTXRES = $(LINTLIBDIR)/llib-lXRes.ln + + DMXLIBSRC = $(LIBSRC)/dmx + +SODMXREV = 1.0 +DEPDMXLIB = +DMXLIB = -ldmx + +LINTDMX = $(LINTLIBDIR)/llib-ldmx.ln + + DPSLIBSRC = $(LIBSRC)/dps + +DEPDPSLIB = $(USRLIBDIR)/libdps.a +DPSLIB = -ldps + +LINTDPS = $(LINTLIBDIR)/llib-ldps.ln + + DPSTKLIBSRC = $(LIBSRC)/dpstk + +DEPDPSTKLIB = $(USRLIBDIR)/libdpstk.a +DPSTKLIB = -ldpstk + +LINTDPSTK = $(LINTLIBDIR)/llib-ldpstk.ln + + PSRESLIBSRC = $(LIBSRC)/psres + +DEPPSRESLIB = $(USRLIBDIR)/libpsres.a +PSRESLIB = -lpsres + +LINTPSRES = $(LINTLIBDIR)/llib-lpsres.ln + + GLULIBSRC = $(LIBSRC)/GLU + +SOGLUREV = 1.3 +DEPGLULIB = +GLULIB = -lGLU + +LINTGLU = $(LINTLIBDIR)/llib-lGLU.ln + + GLXLIBSRC = $(LIBSRC)/GL + +SOGLREV = 1.2 +DEPGLXLIB = +GLXLIB = -lGL + +LINTGLX = $(LINTLIBDIR)/llib-lGL.ln + + GLWIDGETSRC = $(LIBSRC)/GLw + +DEPGLWLIB = $(USRLIBDIR)/libGLw.a +GLWLIB = -lGLw + +LINTGLW = $(LINTLIBDIR)/llib-lGLw.ln + +XRENDERDIR = /usr +XRENDERLIBDIR = /usr/lib +XRENDERINCDIR = /usr/include +XRENDERLIB = -L$(XRENDERLIBDIR) -lXrender +DEPXRENDERLIB = + +XRENDERINCLUDES = -I$(XRENDERINCDIR) + + XRANDRLIBSRC = $(LIBSRC)/Xrandr + +SOXRANDRREV = 2.0 +DEPXRANDRLIB = +XRANDRLIB = -lXrandr + +LINTXRANDR = $(LINTLIBDIR)/llib-lXrandr.ln + + XFIXESLIBSRC = $(LIBSRC)/Xfixes + +SOXFIXESREV = 3.0 +DEPXFIXESLIB = +XFIXESLIB = -lXfixes + +LINTXFIXES = $(LINTLIBDIR)/llib-lXfixes.ln + + XDAMAGELIBSRC = $(LIBSRC)/Xdamage + +SOXDAMAGEREV = 1.0 +DEPXDAMAGELIB = +XDAMAGELIB = -lXdamage + +LINTXDAMAGE = $(LINTLIBDIR)/llib-lXdamage.ln + +XCOMPOSITELIBSRC = $(LIBSRC)/Xcomposite + +SOXCOMPOSITEREV = 1.0 +DEPXCOMPOSITELIB = +XCOMPOSITELIB = -lXcomposite + +LINTXCOMPOSITE = $(LINTLIBDIR)/llib-lXcomposite.ln + +XEVIELIBSRC = $(LIBSRC)/Xevie + +SOXEVIEREV = 1.0 +DEPXEVIELIB = +XEVIELIB = -lXevie + +LINTXEVIE = $(LINTLIBDIR)/llib-lXevie.ln + +XCURSORDIR = /usr +XCURSORLIBDIR = /usr/lib +XCURSORINCDIR = /usr/include +XCURSORLIB = -L$(XCURSORLIBDIR) -lXcursor + +XCURSORINCLUDES=-I$(XCURSORINCDIR) $(XRENDERINCLUDES) + + APPLEWMLIBSRC = $(LIBSRC)/apple + +DEPAPPLEWMLIB = $(USRLIBDIR)/libAppleWM.a +APPLEWMLIB = -lAppleWM + +LINTAPPLEWM = $(LINTLIBDIR)/llib-lAppleWM.ln + + WINDOWSWMLIBSRC = $(LIBSRC)/windows + +DEPWINDOWSWMLIB = $(USRLIBDIR)/libWindowsWM.a +WINDOWSWMLIB = -lWindowsWM + +LINTWINDOWSWM = $(LINTLIBDIR)/llib-lWindowsWM.ln + + XFONTCACHELIBSRC = $(LIBSRC)/Xfontcache + +DEPXFONTCACHELIB = $(USRLIBDIR)/libXfontcache.a +XFONTCACHELIB = -lXfontcache + +LINTXFONTCACHE = $(LINTLIBDIR)/llib-lXfontcache.ln + + XAUTHSRC = $(LIBSRC)/Xau + +SOXAUTHREV = 6.0 +DEPXAUTHLIB = +XAUTHLIB = -lXau + +LINTXAUTH = $(LINTLIBDIR)/llib-lXau.ln + + XDMCPLIBSRC = $(LIBSRC)/Xdmcp + +SOXDMCPREV = 6.0 +DEPXDMCPLIB = +XDMCPLIB = -lXdmcp + +LINTXDMCP = $(LINTLIBDIR)/llib-lXdmcp.ln + + XMUSRC = $(LIBSRC)/Xmu + +SOXMUREV = 6.2 +DEPXMULIB = +XMULIB = -lXmu + +LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln + + XMUUSRC = $(LIBSRC)/Xmuu + +SOXMUUREV = 1.0 +DEPXMUULIB = +XMUULIB = -lXmuu + +LINTXMUU = $(LINTLIBDIR)/llib-lXmuu.ln + + OLDXLIBSRC = $(LIBSRC)/oldX + +DEPOLDXLIB = $(USRLIBDIR)/liboldX.a +OLDXLIB = -loldX + +LINTOLDX = $(LINTLIBDIR)/llib-loldX.ln + + XPLIBSRC = $(LIBSRC)/Xp + +SOXPREV = 6.2 +DEPXPLIB = +XPLIB = -lXp + +LINTXP = $(LINTLIBDIR)/llib-lXp.ln + + TOOLKITSRC = $(LIBSRC)/Xt + +SOXTREV = 6.0 +DEPXTOOLONLYLIB = +XTOOLONLYLIB = -lXt + +LINTXTOOLONLY = $(LINTLIBDIR)/llib-lXt.ln + + DEPXTOOLLIB = $(DEPXTOOLONLYLIB) $(DEPSMLIB) $(DEPICELIB) + XTOOLLIB = $(XTOOLONLYLIB) $(SMLIB) $(ICELIB) + LINTXTOOLLIB = $(LINTXTOOLONLYLIB) + + XALIBSRC = $(LIBSRC)/Xa + +SOXAREV = 1.0 +DEPXALIB = +XALIB = -lXa + +LINTXA = $(LINTLIBDIR)/llib-lXa.ln + + AWIDGETSRC = $(LIBSRC)/Xaw + +SOXAWREV = 8.0 +DEPXAWLIB = +XAWLIB = -lXaw + +LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln + + AWIDGET7SRC = $(LIBSRC)/Xaw7 + +SOXAW7REV = 7.0 +DEPXAW7LIB = +XAW7LIB = -lXaw + +LINTXAW7 = $(LINTLIBDIR)/llib-lXaw.ln + + AWIDGET6SRC = $(LIBSRC)/Xaw6 + +SOXAW6REV = 6.1 +DEPXAW6LIB = +XAW6LIB = -lXaw + +LINTXAW6 = $(LINTLIBDIR)/llib-lXaw.ln + + XILIBSRC = $(LIBSRC)/Xi + +SOXINPUTREV = 6.0 +DEPXILIB = +XILIB = -lXi + +LINTXI = $(LINTLIBDIR)/llib-lXi.ln + + XTESTLIBSRC = $(LIBSRC)/Xtst + +SOXTESTREV = 6.1 +DEPXTESTLIB = +XTESTLIB = -lXtst + +LINTXTEST = $(LINTLIBDIR)/llib-lXtst.ln + +DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a +XBSDLIB = -lXbsd + +LINTXBSD = $(LINTLIBDIR)/llib-lXbsd.ln + + ICESRC = $(LIBSRC)/ICE + +SOICEREV = 6.4 +DEPICELIB = +ICELIB = -lICE + +LINTICE = $(LINTLIBDIR)/llib-lICE.ln + + SMSRC = $(LIBSRC)/SM + +SOSMREV = 6.0 +DEPSMLIB = +SMLIB = -lSM + +LINTSM = $(LINTLIBDIR)/llib-lSM.ln + + XKEYSRC = $(LIBSRC)/Xkey + +SOXKEYREV = 6.0 +DEPXKEYLIB = +XKEYLIB = -lXkey + +LINTXKEY = $(LINTLIBDIR)/llib-lXkey.ln + + FSLIBSRC = $(LIBSRC)/FS + +SOFSREV = 6.0 +DEPFSLIB = +FSLIB = -lFS + +LINTFS = $(LINTLIBDIR)/llib-lFS.ln + + FONTLIBSRC = $(LIBSRC)/font + +DEPFONTLIB = $(USRLIBDIR)/libXfont.a +FONTLIB = -L$(FREETYPELIBDIR) -L$(FONTLIBSRC) -lXfont + +LINTXFONT = $(LINTLIBDIR)/llib-lXfont.ln +# +DEPXFONTLIB = $(USRLIBDIR)/libXfont.a +XFONTLIB = -lXfont + +LINTXFONT = $(LINTLIBDIR)/llib-lXfont.ln + + FONTSTUBLIBSRC = $(FONTLIBSRC)/stubs + +DEPFONTSTUBLIB = $(USRLIBDIR)/libfntstubs.a +FONTSTUBLIB = -lfntstubs + +LINTFONTSTUB = $(LINTLIBDIR)/llib-lfntstubs.ln + DEPFONTLIB = $(DEPXFONTLIB) $(DEPFONTSTUBLIB) + FONTLIB = $(XFONTLIB) $(FONTSTUBLIB) $(FREETYPE2LIB) + + FONTENCLIBSRC = $(LIBSRC)/fontenc + +DEPXFONTENCLIB = $(USRLIBDIR)/libfontenc.a +XFONTENCLIB = -lfontenc + +LINTXFONTENC = $(LINTLIBDIR)/llib-lfontenc.ln + + XPMLIBSRC = $(LIBSRC)/Xpm + +SOXPMREV = 4.11 +DEPXPMLIB = +XPMLIB = -lXpm + +LINTXPM = $(LINTLIBDIR)/llib-lXpm.ln + +FREETYPE2DIR = /usr +FREETYPE2LIBDIR = /usr/lib +FREETYPE2INCDIR = /usr/include + +FREETYPE2LIB = -lfreetype + +FREETYPE2INCLUDES = -I$(FREETYPE2INCDIR)/freetype2 -I$(FREETYPE2INCDIR)/freetype2/config + +FREETYPE2DEFINES = -DFREETYPE2 + + EXPATLIBSRC = $(LIBSRC)/expat + +SOEXPATREV = 0.4 +DEPEXPATLIB = +EXPATLIB = -lexpat + +LINTEXPAT = $(LINTLIBDIR)/llib-lexpat.ln + +EXPATDIR = /usr +EXPATLIBDIR = /usr/lib +EXPATINCDIR = /usr/include + +EXPATINCLUDES = + +EXPATLIB = -lexpat + +EXPATDEFINES = -DEXPAT + +XFTDIR = /usr +XFTLIBDIR = /usr/lib +XFTINCDIR = /usr/include +XFTLIB = -L$(XFTLIBDIR) -lXft + +XFTINCLUDES= -I$(XFTINCDIR) $(FONTCONFIGINCLUDES) $(FREETYPE2INCLUDES) $(XRENDERINCLUDES) + +FONTCONFIGDIR = /usr +FONTCONFIGLIBDIR = /usr/lib +FONTCONFIGINCDIR = /usr/include +FONTCONFIGBINDIR = /usr/bin + +FONTCONFIGLIB = -lfontconfig + +FONTCONFIGINCLUDES = + +FCCACHE = $(FONTCONFIGBINDIR)/fc-cache + +FONTCONFIGDEFINES = -DFONTCONFIG + +LIBPNGINCDIR = /usr/include + +LIBPNGINC= + +LIBPNGDIR = /usr +LIBPNGLIBDIR = /usr/lib +LIBPNGINCDIR = /usr/include + +LIBPNGLIB = -lpng + + XKBFILELIBSRC = $(LIBSRC)/xkbfile + +SOXKBFILEREV = 1.0 +DEPXKBFILELIB = +XKBFILELIB = -lxkbfile + +LINTXKBFILE = $(LINTLIBDIR)/llib-lxkbfile.ln + + XKBCOMPCMD = $(XBINDIR)/xkbcomp + + XKBUILIBSRC = $(LIBSRC)/xkbui + +SOXKBUIREV = 1.0 +DEPXKBUILIB = +XKBUILIB = -lxkbui + +LINTXKBUI = $(LINTLIBDIR)/llib-lxkbui.ln + +EXTRAXAWREQS = + +EXTRAXAWCLIENTDEPLIBS = + +EXTRAXAWCLIENTLIBS = + + XTRAPLIBSRC = $(LIBSRC)/XTrap + +SOXTRAPREV = 6.4 +DEPXTRAPLIB = +XTRAPLIB = -lXTrap + +LINTXTRAP = $(LINTLIBDIR)/llib-lXTrap.ln + + DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB) + + DEPLIBS1 = $(DEPLIBS) + DEPLIBS2 = $(DEPLIBS) + DEPLIBS3 = $(DEPLIBS) + DEPLIBS4 = $(DEPLIBS) + DEPLIBS5 = $(DEPLIBS) + DEPLIBS6 = $(DEPLIBS) + DEPLIBS7 = $(DEPLIBS) + DEPLIBS8 = $(DEPLIBS) + DEPLIBS9 = $(DEPLIBS) + DEPLIBS10 = $(DEPLIBS) + + XFTPRELOADPATTERN = libXft.so.? + XRENDERPRELOADPATTERN = libXrender.so.? + XFONTPRELOADPATTERN = libXfont*.so.? + +XMULIBONLY = -lXmu +XMULIB = $(XMULIBONLY) $(XTOOLLIB) $(XLIB) + + CONFIGDIR = $(LIBDIR)/config + + USRLIBDIRPATH = $(USRLIBDIR) + LDPRELIBS = $(INSTALLED_LIBS) + LDPOSTLIBS = + TOP_INCLUDES = $(TOP_X_INCLUDES) + PROJECT_DEFINES = + VENDOR_DEFINES = -DXVENDORNAME='"$(VENDORNAME)"' -DXVENDORNAMESHORT='"$(VENDORNAMESHORT)"' + +CXXPROJECT_DEFINES = + +# ---------------------------------------------------------------------- +# start of Imakefile + +# +# +# + +all:: + +world:: + make ${MFLAGS} mastermakefiles + make ${MFLAGS} depend + make ${MFLAGS} all + + SUBDIRS = Cl HText Xl Ui erwise + +all:: + @for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[ik]*) set +e;; esac; done; \ + for i in $(SUBDIRS) ;\ + do \ + echo "making" all "in $(CURRENT_DIR)/$$i..."; \ + $(MAKE) -C $$i $(MFLAGS) $(PARALLELMFLAGS) 'CC=$(CC)' 'CDEBUGFLAGS=$(CDEBUGFLAGS)' all; \ + done + +depend:: + @for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[ik]*) set +e;; esac; done; \ + for i in $(SUBDIRS) ;\ + do \ + echo "depending" "in $(CURRENT_DIR)/$$i..."; \ + $(MAKE) -C $$i $(MFLAGS) $(PARALLELMFLAGS) 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 + +.c.i: + $(RM) $@ + $(CC) -E $(CFLAGS) $(_NOOP_) $*.c > $@ + +.SUFFIXES: .ii + +.cc.ii: + $(RM) $@ + $(CC) -E $(CFLAGS) $(_NOOP_) $*.cc > $@ + +.SUFFIXES: .s + +.c.s: + $(RM) $@ + $(CC) -S $(CFLAGS) $(_NOOP_) $*.c + +.cc.s: + $(RM) $@ + $(CC) -S $(CFLAGS) $(_NOOP_) $*.cc + +emptyrule:: + +cleandir:: + $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut "#"* + +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 + +man_keywords:: + +html_index:: + +clean:: cleandir + +distclean:: cleandir + +# ---------------------------------------------------------------------- +# rules for building in SUBDIRS - do not edit + +install:: + @for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[ik]*) set +e;; esac; done; \ + for i in $(SUBDIRS) ;\ + do \ + echo "installing" "in $(CURRENT_DIR)/$$i..."; \ + $(MAKE) -C $$i $(MFLAGS) $(PARALLELMFLAGS) DESTDIR=$(DESTDIR) install; \ + done + +install.man:: + @for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[ik]*) set +e;; esac; done; \ + for i in $(SUBDIRS) ;\ + do \ + echo "installing man pages" "in $(CURRENT_DIR)/$$i..."; \ + $(MAKE) -C $$i $(MFLAGS) $(PARALLELMFLAGS) DESTDIR=$(DESTDIR) install.man; \ + done + +install.sdk:: + @for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[ik]*) set +e;; esac; done; \ + for i in $(SUBDIRS) ;\ + do \ + echo "installing driver SDK" "in $(CURRENT_DIR)/$$i..."; \ + $(MAKE) -C $$i $(MFLAGS) $(PARALLELMFLAGS) DESTDIR='$(DESTDIR)' install.sdk; \ + done + +clean:: + @for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[ik]*) set +e;; esac; done; \ + for i in $(SUBDIRS) ;\ + do \ + echo "cleaning" "in $(CURRENT_DIR)/$$i..."; \ + $(MAKE) -C $$i $(MFLAGS) $(PARALLELMFLAGS) clean; \ + done + +tags:: + @for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[ik]*) set +e;; esac; done; \ + for i in $(SUBDIRS) ;\ + do \ + echo "tagging" "in $(CURRENT_DIR)/$$i..."; \ + $(MAKE) -C $$i $(MFLAGS) $(PARALLELMFLAGS) TAGS='$(TAGS)' tags; \ + done + +$(ONESUBDIR)/Makefile: + @for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[n]*) executeit="no";; esac; done; \ + cd $(ONESUBDIR) && \ + if [ "$$executeit" != "no" ]; then \ + $(IMAKE_CMD) -DTOPDIR=$(IMAKETOP) -DCURDIR=$(ONECURDIR)$(ONESUBDIR); \ + fi; + +Makefiles:: + -@for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[ik]*) set +e;; esac; done; \ + for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[n]*) executeit="no";; esac; done; \ + for i in $(SUBDIRS) ;\ + do \ + case "$(CURRENT_DIR)" in \ + .) curdir= ;; \ + *) curdir=$(CURRENT_DIR)/ ;; \ + esac; \ + echo "making Makefiles in $$curdir$$i..."; \ + itmp=`echo $$i | sed -e 's;^\./;;g' -e 's;/\./;/;g'`; \ + curtmp="$(CURRENT_DIR)" \ + toptmp=""; \ + case "$$itmp" in \ + ../?*) \ + while echo "$$itmp" | grep '^\.\./' > /dev/null;\ + do \ + toptmp="/`basename $$curtmp`$$toptmp"; \ + curtmp="`dirname $$curtmp`"; \ + itmp="`echo $$itmp | sed 's;\.\./;;'`"; \ + done \ + ;; \ + esac; \ + case "$$itmp" in \ + */?*/?*/?*/?*) newtop=../../../../..;; \ + */?*/?*/?*) newtop=../../../..;; \ + */?*/?*) newtop=../../..;; \ + */?*) newtop=../..;; \ + *) newtop=..;; \ + esac; \ + newtop="$$newtop$$toptmp"; \ + case "$(TOP)" in \ + /?*) imaketop=$(TOP) \ + imakeprefix= ;; \ + .) imaketop=$$newtop \ + imakeprefix=$$newtop/ ;; \ + *) imaketop=$$newtop/$(TOP) \ + imakeprefix=$$newtop/ ;; \ + esac; \ + $(RM) $$i/Makefile.bak; \ + if [ -f $$i/Makefile ]; then \ + echo " $(MV) Makefile Makefile.bak"; \ + if [ "$$executeit" != "no" ]; then \ + $(MV) $$i/Makefile $$i/Makefile.bak; \ + fi; \ + fi; \ + $(MAKE) $(MFLAGS) $(MAKE_OPTS) ONESUBDIR=$$i ONECURDIR=$$curdir IMAKETOP=$$imaketop IMAKEPREFIX=$$imakeprefix $$i/Makefile; \ + if [ -d $$i ] ; then \ + cd $$i; \ + $(MAKE) $(MFLAGS) Makefiles; \ + cd $$newtop; \ + else \ + exit 1; \ + fi; \ + done + +includes:: + @for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[ik]*) set +e;; esac; done; \ + for i in $(SUBDIRS) ;\ + do \ + echo including "in $(CURRENT_DIR)/$$i..."; \ + $(MAKE) -C $$i $(MFLAGS) $(PARALLELMFLAGS) includes; \ + done + +distclean:: + @for flag in ${MAKEFLAGS} ''; do \ + case "$$flag" in *=*) ;; --*) ;; *[ik]*) set +e;; esac; done; \ + for i in $(SUBDIRS) ;\ + do \ + echo "cleaning" "in $(CURRENT_DIR)/$$i..."; \ + $(MAKE) -C $$i $(MFLAGS) $(PARALLELMFLAGS) distclean; \ + done + + PREPROCESSMANPAGES = true + +distclean:: + $(RM) Makefile Makefile.dep + +# ---------------------------------------------------------------------- +# dependencies generated by makedepend + diff --git a/README b/README new file mode 100644 index 0000000..032c789 --- /dev/null +++ b/README @@ -0,0 +1,6 @@ +This is erwise as fetched from: ftp://ftp.funet.fi/pub/networking/services/www/erwisE/ + +Patched by Toni Nikkanen to compile and run on Nokia N810/800 etc. Maemo +devices, using Diablo 4.1.2 SDK. +Included are the required lesstif libraries under lesstif-libs/ + diff --git a/Ui/Imakefile b/Ui/Imakefile new file mode 100644 index 0000000..257cb3f --- /dev/null +++ b/Ui/Imakefile @@ -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 index 0000000..d696b5c --- /dev/null +++ b/Ui/Makefile @@ -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 +# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $ +# +# Platform-specific parameters may be set in the appropriate .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 index 0000000..4d2bd2a --- /dev/null +++ b/Ui/RCS/.uidemo.c,v @@ -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 +#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 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 index 0000000..8c2863d --- /dev/null +++ b/Ui/UiConnections.c @@ -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 index 0000000..09053e1 --- /dev/null +++ b/Ui/UiControlPanel.c @@ -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 index 0000000..a2c6892 --- /dev/null +++ b/Ui/UiDefaults.c @@ -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 index 0000000..a0943f9 --- /dev/null +++ b/Ui/UiDefs.h @@ -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 index 0000000..a880c2f --- /dev/null +++ b/Ui/UiFileSelection.c @@ -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 index 0000000..632584e --- /dev/null +++ b/Ui/UiIncludes.h @@ -0,0 +1,40 @@ +/* $Id: UiIncludes.h,v 1.3 1992/03/26 18:13:50 kny Exp kny $ */ + + +#include +#include +#include +/* Toni */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..4c13503 --- /dev/null +++ b/Ui/UiInfo.c @@ -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 index 0000000..330d1ad --- /dev/null +++ b/Ui/UiInit.c @@ -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 index 0000000..bb332fd --- /dev/null +++ b/Ui/UiList.c @@ -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 index 0000000..47b388b --- /dev/null +++ b/Ui/UiMisc.c @@ -0,0 +1,617 @@ +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(int *nargs, ...) +{ + static Arg args[50]; + String tmpstr; + va_list pvar; + + *nargs = 0; + + va_start(pvar,nargs); + 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); Toni */ + + 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 index 0000000..f869520 --- /dev/null +++ b/Ui/UiPage.c @@ -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 index 0000000..f572d7b --- /dev/null +++ b/Ui/UiPageSettings.c @@ -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 index 0000000..6d6f856 --- /dev/null +++ b/Ui/UiPrint.c @@ -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 index 0000000..321e123 --- /dev/null +++ b/Ui/UiProtos.h @@ -0,0 +1,95 @@ +/* $Id: UiProtos.h,v 1.4 1992/03/26 18:13:50 kny Exp kny $ */ + + +/* + * Misc. prototypes (external to library) + */ +/* Toni */ +/* 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); +/* Toni */ +extern ArgList uiVaSetArgs( int *nargs, ...); +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 index 0000000..978ff8a --- /dev/null +++ b/Ui/UiRecall.c @@ -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 index 0000000..e3c8648 --- /dev/null +++ b/Ui/UiSearch.c @@ -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 index 0000000..52a644a --- /dev/null +++ b/Ui/UiSelectionBox.c @@ -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 index 0000000..48939d8 --- /dev/null +++ b/Ui/UiTypes.h @@ -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 index 0000000..30e72cc --- /dev/null +++ b/Ui/UiUtil.c @@ -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 index 0000000..cd05a8e --- /dev/null +++ b/Xl/Imakefile @@ -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 index 0000000..c4f0561 --- /dev/null +++ b/Xl/Makefile @@ -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 +# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $ +# +# Platform-specific parameters may be set in the appropriate .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 index 0000000..e413943 --- /dev/null +++ b/Xl/Xl.h @@ -0,0 +1,44 @@ +/* + * Xl.h -- + * + * Author: Teemu Rantanen + * 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 index 0000000..0d37f97 --- /dev/null +++ b/Xl/XlConfig.h @@ -0,0 +1,34 @@ +/* + * XlConfig.h -- + * + * Author: Teemu Rantanen + * 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 index 0000000..4961a5d --- /dev/null +++ b/Xl/XlDefaultFonts.h @@ -0,0 +1,47 @@ +/* + * XlDefaultFonts.h -- + * + * Author: Teemu Rantanen + * 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 index 0000000..f97bdbf --- /dev/null +++ b/Xl/XlFormatText.c @@ -0,0 +1,573 @@ +/* + * XlFormatText.c -- + * + * Author: Teemu Rantanen + * 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 +#include +#include + +#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, + ¤t_left, ¤t_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, + ¤t_left, ¤t_right, + &x, &y, low_y, MARGIN_START_STYLE); + break; + + case HTEXT_TAB: + + xl_set_margins(p, leftmargin, leftmargin + width, + ¤t_left, ¤t_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, + ¤t_left, ¤t_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, + ¤t_left, ¤t_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, + ¤t_left, ¤t_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, + ¤t_left, ¤t_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 index 0000000..e5391ad --- /dev/null +++ b/Xl/XlFormatText.h @@ -0,0 +1,61 @@ +/* + * XlFormatText.h -- + * + * Author: Teemu Rantanen + * 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 index 0000000..6846aec --- /dev/null +++ b/Xl/XlSetup.c @@ -0,0 +1,372 @@ +/* + * XlSetup.c -- + * + * Author: Teemu Rantanen + * 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 +#include + +#include + +#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, ¤tgc, 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 index 0000000..24ff490 --- /dev/null +++ b/Xl/XlStyle.c @@ -0,0 +1,286 @@ +/* + * XlStyle.c -- + * + * Author: Teemu Rantanen + * 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 +#include + +#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 index 0000000..1af12ed --- /dev/null +++ b/Xl/XlStyle.h @@ -0,0 +1,86 @@ +/* + * XlStyle.h -- + * + * Author: Teemu Rantanen + * 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 index 0000000..9a3e771 --- /dev/null +++ b/Xl/XlTypes.h @@ -0,0 +1,92 @@ +/* + * XlTypes.h -- + * + * Author: Teemu Rantanen + * 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 index 0000000..f513d94 --- /dev/null +++ b/Xl/XlUtil.c @@ -0,0 +1,289 @@ +/* + * XlUtil.c -- + * + * Author: Teemu Rantanen + * 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 +#include + +#include + +#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 index 0000000..d194dc0 --- /dev/null +++ b/Xl/XlWindow.c @@ -0,0 +1,358 @@ +/* + * XlWindow.c -- + * + * Author: Teemu Rantanen + * 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 +#include + +#include + +#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/debian/changelog b/debian/changelog new file mode 100644 index 0000000..5574368 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,6 @@ +erwise (0.1-1) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- Toni Nikkanen Sat, 7 Mar 2009 20:49:16 +0200 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..ce19db2 --- /dev/null +++ b/debian/control @@ -0,0 +1,11 @@ +Source: erwise +Section: user/other +Priority: extra +Maintainer: Toni Nikkanen +Build-Depends: debhelper (>= 5) +Standards-Version: 3.7.2 + +Package: erwise +Architecture: any +Depends: ${shlibs:Depends} +Description: The first graphical WWW browser from year 1992 diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..0032291 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,22 @@ +This package was debianized by Toni Nikkanen on +Sat, 7 Mar 2009 20:49:16 +0200. + +It was downloaded from + +Upstream Author: + +Copyright: + +License: + + + + +The Debian packaging is (C) 2009, Toni Nikkanen and +is licensed under the GPL, see `/usr/share/common-licenses/GPL'. + + +# Please also look if there are files or directories which have a +# different copyright/license attached and list them here. + diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..85a60b4 --- /dev/null +++ b/debian/dirs @@ -0,0 +1,4 @@ +usr/bin +usr/lib +usr/share/applications/hildon +usr/share/dbus-1/services diff --git a/debian/erwise.desktop b/debian/erwise.desktop new file mode 100644 index 0000000..fccb5b2 --- /dev/null +++ b/debian/erwise.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=0.1 +Type=Application +Name=ErwisE +Exec=/usr/bin/erwise +Icon=qgn_list_gene_default_app diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..aca4b51 --- /dev/null +++ b/debian/rules @@ -0,0 +1,107 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +export DH_VERBOSE=1 + + + + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + + touch configure-stamp + + +build: build-stamp + +build-stamp: configure-stamp + echo MORO1 + dh_testdir + echo MORO2 + + # Add here commands to compile the package. + make + #docbook-to-man debian/erwise.sgml > erwise.1 + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) clean + find . -name *.a|xargs rm -vf + find . -name *.o|xargs rm -vf + + dh_clean + echo MORO3 + +install: build + echo MORO4 + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + echo MORO5 + + # Add here commands to install the package into debian/erwise. + install erwise/erwise debian/erwise/usr/bin/ + install lesstif-libs/* debian/erwise/usr/lib/ + install debian/erwise.desktop debian/erwise/usr/share/applications/hildon/ + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/erwise/Config.c b/erwise/Config.c new file mode 100644 index 0000000..5bd81a2 --- /dev/null +++ b/erwise/Config.c @@ -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 index 0000000..6f34278 --- /dev/null +++ b/erwise/Defs.h @@ -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 index 0000000..105fee3 --- /dev/null +++ b/erwise/Help.c @@ -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 index 0000000..e2a5dd0 --- /dev/null +++ b/erwise/Imakefile @@ -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 index 0000000..72ecbe7 --- /dev/null +++ b/erwise/Includes.h @@ -0,0 +1,15 @@ +/* $Id: Includes.h,v 1.1 1992/05/18 21:43:03 tvr Exp tvr $ */ + + +#include +#include +#include + +#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 index 0000000..c9fd768 --- /dev/null +++ b/erwise/Makefile @@ -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 +# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $ +# +# Platform-specific parameters may be set in the appropriate .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 = /usr/X11R6 + + 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 = /usr/X11R6/lib + BINDIR = /usr/X11R6/bin + INCROOT = /usr/X11R6/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 = /usr/X11R6/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 = + XMULIBONLY = -lXmu + XMULIB = -lXmu + + DEPOLDXLIB = + OLDXLIB = -loldX + + DEPXTOOLLIB = + XTOOLLIB = -lXt + + DEPXAWLIB = + 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 index 0000000..82c9f73 --- /dev/null +++ b/erwise/Misc.c @@ -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 index 0000000..7b97a21 --- /dev/null +++ b/erwise/Page.c @@ -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 index 0000000..362995d --- /dev/null +++ b/erwise/Print.c @@ -0,0 +1,526 @@ +/* + * Print.c -- + * + * Author: Teemu Rantanen 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 + +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 index 0000000..6e843bb --- /dev/null +++ b/erwise/Protos.h @@ -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 index 0000000..0e995ec --- /dev/null +++ b/erwise/Setup.c @@ -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 index 0000000..a9d13d9 --- /dev/null +++ b/erwise/TopLevel.c @@ -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 index 0000000..992810b --- /dev/null +++ b/erwise/Types.h @@ -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 index 0000000..788ba62 --- /dev/null +++ b/erwise/main.c @@ -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 diff --git a/lesstif-libs/libXm.so b/lesstif-libs/libXm.so new file mode 120000 index 0000000..94dc836 --- /dev/null +++ b/lesstif-libs/libXm.so @@ -0,0 +1 @@ +libXm.so.2 \ No newline at end of file diff --git a/lesstif-libs/libXm.so.2 b/lesstif-libs/libXm.so.2 new file mode 120000 index 0000000..3dbebb4 --- /dev/null +++ b/lesstif-libs/libXm.so.2 @@ -0,0 +1 @@ +libXm.so.2.0.1 \ No newline at end of file diff --git a/lesstif-libs/libXm.so.2.0.1 b/lesstif-libs/libXm.so.2.0.1 new file mode 100755 index 0000000..d246ded Binary files /dev/null and b/lesstif-libs/libXm.so.2.0.1 differ