This is slhelp.c in view mode; [Download] [Up]
#include <stdio.h>
#ifdef unix
# include <signal.h>
# ifndef sun
# include <sys/ioctl.h>
# endif
# ifdef HAS_TERMIOS
# include <termios.h>
# endif
#endif
#include "slang.h"
#ifndef HELP_DIR
#define HELP_DIR ""
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
typedef struct SLhlp_Node_Type
{
char *name;
struct SLhlp_Node_Type *child;
struct SLhlp_Node_Type *sister;
unsigned long pos;
} SLhlp_Node_Type;
typedef struct
{
FILE *fp;
SLhlp_Node_Type *root;
SLhlp_Node_Type *sub; /* current subtopic node */
SLhlp_Node_Type *now; /* Node we are currently reading from */
SLhlp_Node_Type *path[10]; /* path to current node */
int level;
} SLhlp_File_Type;
#define MAX_HELP_FILES 10
SLhlp_File_Type Help_Files[MAX_HELP_FILES];
static int add_level (int level, int fd, char *name, unsigned long pos)
{
SLhlp_Node_Type *node, *parent, *new_node;
int len;
while (*name == ' ') name++;
len = strlen(name);
if (len) while (name[len - 1] == ' ') len--;
if (len == 0) return -1;
name[len] = 0;
parent = node = Help_Files[fd].root;
while (level-- > 0)
{
if (node == NULL)
{
return -1;
}
while (node->sister != NULL) node = node->sister;
parent = node;
node = node->child;
}
if ((NULL == (new_node = (SLhlp_Node_Type *) SLMALLOC (sizeof (SLhlp_Node_Type))))
|| (NULL == (new_node->name = (char *) SLMALLOC (len + 1))))
{
SLang_Error = SL_MALLOC_ERROR;
return -1;
}
new_node->sister = NULL;
new_node->child = NULL;
new_node->pos = pos;
strcpy (new_node->name, name);
if (node == NULL)
{
if (parent == NULL)
{
Help_Files[fd].root = new_node;
}
else parent->child = new_node;
}
else
{
while (node->sister != NULL) node = node->sister;
node->sister = new_node;
}
return 0;
}
static void free_nodes (SLhlp_Node_Type *node)
{
if (node->child != NULL) free_nodes (node->child);
if (node->sister != NULL) free_nodes (node->sister);
if (node->name != NULL) SLFREE (node->name);
SLFREE (node);
}
static int check_fd (int fd)
{
if (((fd >= MAX_HELP_FILES) || (fd < 0)) || (Help_Files[fd].fp == NULL))
{
if (SLang_Error == 0) SLang_Error = INTRINSIC_ERROR;
return 0;
}
return 1;
}
void SLhlp_close_help (int fd)
{
if (!check_fd (fd)) return;
fclose (Help_Files[fd].fp); Help_Files[fd].fp = NULL;
if (Help_Files[fd].root != NULL) free_nodes (Help_Files[fd].root);
}
int SLhlp_open_help (char *file)
{
int fd = 0, ch;
FILE *fp;
int level;
char topic[256], *b;
unsigned long pos;
while ((fd < MAX_HELP_FILES) && (Help_Files[fd].fp != NULL))
fd++;
if (fd == MAX_HELP_FILES) return -1;
if (NULL == (Help_Files[fd].fp = fp = fopen (file, "r"))) return -1;
while (1)
{
ch = getc (fp);
bypass_getc:
if ((ch > '9') || (ch == ' ')) continue;
if (ch == '\n')
{
ch = getc (fp);
if ((ch == ' ') || (ch > '9')) continue;
if (ch >= '1')
{
level = ch - '1';
pos = ftell (fp);
b = topic;
while (('\n' != (ch = getc (fp))) && (ch != EOF))
{
*b++ = ch;
}
*b = 0;
if (add_level (level, fd, topic, pos)) goto error;
}
goto bypass_getc;
}
if (ch == EOF) break;
}
Help_Files[fd].now = NULL;
Help_Files[fd].sub = Help_Files[fd].root;
Help_Files[fd].path[0] = NULL;
return fd;
error:
SLhlp_close_help (fd);
return -1;
}
char *SLhlp_get_subtopic (int fd)
{
SLhlp_Node_Type *node;
if (!check_fd(fd)) return NULL;
if ((node = Help_Files[fd].sub) == NULL) return NULL;
Help_Files[fd].sub = node->sister;
return node->name;
}
char *SLhlp_gets (int fd, char *buf)
{
SLhlp_Node_Type *node;
char ch;
if (!check_fd(fd)) return NULL;
node = Help_Files[fd].now;
if (node == NULL) return NULL;
if ((NULL == fgets(buf, 255, Help_Files[fd].fp))
|| ((*buf <= '9') && (*buf >= '0')))
{
if ((node->child == NULL) && Help_Files[fd].level)
{
Help_Files[fd].level--;
}
Help_Files[fd].now = NULL;
return NULL;
}
/* First character is reserved. */
if (*buf > ' ')
{
ch = *buf | 0x20;
if ((ch < 'a') || (ch > 'z'))
{
*buf = '\n';
*(buf + 1) = 0;
}
}
return buf;
}
static int my_strncasecmp (char *a, char *b, int n)
{
register char cha, chb;
while (n--)
{
cha = *a++;
chb = *b++;
if (cha != 0)
{
if ((cha == chb)
|| ((cha | 0x20) == (chb | 0x20))) continue;
}
return cha - chb;
}
return 0;
}
int SLhlp_select_topic (int fd, char *topic)
{
char topic_buf[256];
char *t, ch;
int level = 0;
int len;
SLhlp_Node_Type *node, *parent;
if (!check_fd (fd)) return -1;
parent = node = Help_Files[fd].root;
ch = 0;
if (topic != NULL)
while (((ch = *topic) <= ' ') && ch) topic++;
if (ch != 0) while (node != NULL)
{
parent = node;
t = topic_buf;
while ((ch = *topic) > ' ')
{
*t++ = ch;
topic++;
}
while (((ch = *topic) <= ' ') && ch) topic++;
*t = 0;
len = strlen (topic_buf);
if (len) while (my_strncasecmp (node->name, topic_buf, len))
{
node = node->sister;
if (node == NULL) break;
}
if (node == NULL) break;
Help_Files[fd].path[level++] = node;
if ((ch == 0) || (ch == '\n')) break;
node = node -> child;
}
/* level comes out at 1 greater than last valid one */
Help_Files[fd].level = level;
if (node != NULL) /* success */
{
Help_Files[fd].sub = node->child;
Help_Files[fd].now = node;
fseek (Help_Files[fd].fp, node->pos, SEEK_SET);
return 0;
}
else /* failure */
{
Help_Files[fd].now = NULL;
Help_Files[fd].sub = parent;
return -1;
}
}
int SLhlp_what_topic (int fd, char *buf)
{
int level, i;
char *b;
if (!check_fd(fd)) return -1;
level = Help_Files[fd].level;
*buf = 0;
if (level == 0) return 0;
b = buf;
for (i = 0; i < level; i++)
{
strcpy (b, Help_Files[fd].path[i]->name);
b = b + strlen (b);
*b++ = ' ';
}
*(b - 1) = 0;
return level;
}
int SLhlp_up_topic (int fd)
{
if (!check_fd(fd)) return -1;
if (Help_Files[fd].level) Help_Files[fd].level--;
return 0;
}
/* --------------------------------------------------------------------- */
static void cls (void)
{
SLtt_cls ();
SLtt_flush_output ();
}
static void newline (int nl, int reset, int cls_flag)
{
static int n;
if (nl) putc('\n', stdout);
n++;
if (n == SLtt_Screen_Rows - 1)
{
SLtt_reverse_video (1);
SLtt_write_string ("---Press RETURN to continue.---");
SLtt_normal_video ();
SLtt_flush_output ();
SLang_getkey ();
if (cls_flag) cls ();
else
fputs("\r \r", stdout);
cls_flag = 0;
n = 0;
}
if (reset)
{
n = 0;
if (cls_flag) cls ();
return;
}
}
SLang_RLine_Info_Type *Help_Rli;
static SLang_RLine_Info_Type *init_readline (void)
{
unsigned char *buf = NULL;
SLang_RLine_Info_Type *rli;
if ((NULL == (rli = (SLang_RLine_Info_Type *) SLMALLOC (sizeof(SLang_RLine_Info_Type))))
|| (NULL == (buf = (unsigned char *) SLMALLOC (256))))
{
fprintf(stderr, "malloc error.\n");
exit(-1);
}
MEMSET ((char *) rli, 0, sizeof (SLang_RLine_Info_Type));
rli->buf = buf;
rli->buf_len = 255;
rli->tab = 8;
rli->dhscroll = 20;
rli->getkey = SLang_getkey;
rli->tt_goto_column = NULL;
rli->update_hook = NULL;
if (SLang_init_readline (rli) < 0)
{
fprintf(stderr, "Unable to initialize readline library.\n");
exit (-1);
}
return rli;
}
static char *hlp_get_input (char *prompt)
{
int i;
if (Help_Rli == NULL)
{
Help_Rli = init_readline ();
Help_Rli->update_hook = NULL;
}
Help_Rli->edit_width = SLtt_Screen_Cols - 1;
Help_Rli->prompt = prompt;
*Help_Rli->buf = 0;
i = SLang_read_line (Help_Rli);
if ((i >= 0) && !SLang_Error && !SLKeyBoard_Quit)
{
SLang_rline_save_line (Help_Rli);
}
else return NULL;
return (char *) Help_Rli->buf;
}
static void do_subtopics (int fd)
{
char *s;
int len, dlen;
if ((s = SLhlp_get_subtopic (fd)) != NULL)
{
len = 0;
newline (1, 0, 0);
fprintf(stdout, "Available Topics/Subtopics:");
newline (1, 0, 0);
newline (1, 0, 0);
do
{
dlen = strlen (s);
len += dlen;
if (len >= 80)
{
len = dlen;
newline (1, 0, 0);
}
fputs(s, stdout);
dlen = 21 - len % 20;
len += dlen;
if (len < 80)
{
while (dlen--) putc(' ', stdout);
}
}
while (NULL != (s = SLhlp_get_subtopic(fd)));
newline (1, 0, 0);
}
}
static void get_screen_size (int sig)
{
int r = 0, c = 0;
#ifdef VMS
int status, code;
unsigned short chan;
$DESCRIPTOR(dev_dsc, "SYS$INPUT:");
#endif
#ifdef TIOCGWINSZ
struct winsize wind_struct;
if ((ioctl(1,TIOCGWINSZ,&wind_struct) == 0)
|| (ioctl(0, TIOCGWINSZ, &wind_struct) == 0)
|| (ioctl(2, TIOCGWINSZ, &wind_struct) == 0))
{
c = (int) wind_struct.ws_col;
r = (int) wind_struct.ws_row;
}
#endif
#ifdef VMS
status = sys$assign(&dev_dsc,&chan,0,0,0);
if (status & 1)
{
code = DVI$_DEVBUFSIZ;
status = lib$getdvi(&code, &chan,0, &c, 0,0);
if (!(status & 1))
c = 80;
code = DVI$_TT_PAGE;
status = lib$getdvi(&code, &chan,0, &r, 0,0);
if (!(status & 1))
r = 24;
sys$dassgn(chan);
}
#endif
if (r <= 0)
{
char *s = getenv ("LINES");
if (s != NULL) r = atoi (s);
}
if (c <= 0)
{
char *s = getenv ("COLUMNS");
if (s != NULL) c = atoi (s);
}
if ((r <= 0) || (r > 200)) r = 24;
if ((c <= 0) || (c > 250)) c = 80;
SLtt_Screen_Rows = r;
SLtt_Screen_Cols = c;
#ifdef SIGWINCH
signal (SIGWINCH, get_screen_size);
#endif
}
int main (int argc, char **argv)
{
char *buf, *file;
char buffer[256];
static int fd = -1;
int len;
if (argc != 2)
{
fprintf(stderr, "Usage: slhelp HELP-FILE\n");
exit (-1);
}
file = argv[1];
if (fd < 0) fd = SLhlp_open_help (file);
if (fd < 0)
{
fprintf (stderr, "Unable to open help file %s\n", file);
exit (-1);
}
SLang_init_tty (7, 1, 1);
SLtt_get_terminfo ();
SLtt_init_video ();
SLtt_Use_Ansi_Colors = 0;
#ifdef SIGWINCH
signal (SIGWINCH, get_screen_size);
#endif
get_screen_size (0);
cls ();
fputs ("\n\nSimply press RETURN at the 'Topic>' prompt to quit help.\n\n",
stdout);
if (SLhlp_what_topic (fd, buffer) > 0)
{
SLhlp_select_topic (fd, buffer);
}
while (1)
{
while (1)
{
if (SLhlp_what_topic (fd, buffer) <= 0)
{
SLhlp_select_topic (fd, "?");
*buffer = 0;
}
do_subtopics (fd);
len = strlen (buffer);
if (len) strcat (buffer, " Subtopic> ");
else strcpy (buffer, "Topic> ");
newline (1, 1, 0);
if (NULL == (buf = hlp_get_input (buffer)))
{
SLang_Error = 0;
if (SLKeyBoard_Quit)
{
SLKeyBoard_Quit = 0;
continue;
}
goto the_return;
}
if ((*buf == '\n') || (*buf == 0))
{
if (len == 0) goto the_return;
SLhlp_up_topic (fd);
continue;
}
buffer[len] = ' '; /* kill prompt */
strcpy (buffer + (len + 1), buf);
break;
}
newline (1, 1, 1);
if (-1 == SLhlp_select_topic (fd, buffer))
{
fprintf(stdout, "No help available on: %s", buf);
newline (1, 0, 0);
}
else while (NULL != SLhlp_gets (fd, buffer))
{
fputs(buffer, stdout);
newline (0, 0, 1);
}
}
the_return:
SLtt_reset_video ();
SLang_reset_tty ();
return 0;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.