#if 0
static char rcsid[] = "@(#)$Id: help.c 3 2008-02-25 09:49:14Z keaston $";
#endif
#include "irc.h"
static char cvsrevision[] = "$Id: help.c 3 2008-02-25 09:49:14Z keaston $";
CVS_REVISION(help_c)
#ifdef WANT_EPICHELP
#include "struct.h"
#include "help.h"
#include "input.h"
#include "ircaux.h"
#include "hook.h"
#include "output.h"
#include "screen.h"
#include "server.h"
#include "ircterm.h"
#include "vars.h"
#include "window.h"
#include <sys/stat.h>
#include "bsdglob.h"
#define MAIN_SOURCE
#include "modval.h"
static void help_me (char *, char *);
static void help_show_paused_topic (char *, char *);
static void create_help_window (void);
static void set_help_screen (Screen *);
static void help_put_it (const char *topic, const char *format, ...);
static int dont_pause_topic = 0;
static int entry_size;
static int finished_help_paging = 0;
static FILE * help_fp;
#define HELP_PAUSED_LINES_MAX 500
static int help_paused_lines = 0;
static char * help_paused_topic[HELP_PAUSED_LINES_MAX];
static Screen *help_screen = (Screen *) 0;
static int help_show_directory = 0;
static char help_topic_list[BIG_BUFFER_SIZE + 1];
static Window *help_window = (Window *) 0;
static char no_help[] = "NOHELP";
static char paused_topic[128];
static char * this_arg;
static int use_help_window = 0;
static int show_help (Window *window, char *name)
{
Window *old_target_window = target_window;
int rows = 0;
char line[256];
target_window = window ? window : current_window;
if (get_int_var(HELP_PAGER_VAR))
rows = window->display_size;
while (rows)
{
if (!fgets(line, 255, help_fp))
{
fclose(help_fp);
help_fp = NULL;
target_window = old_target_window;
return 0;
}
if (*(line + strlen(line) - 1) == '\n')
*(line + strlen(line) - 1) = (char) 0;
if (*line == '!' || *line == '#')
continue;
help_put_it(name, "%s", line);
rows--;
}
target_window = old_target_window;
return (1);
}
static void help_prompt (char *name, char *line)
{
if (finished_help_paging)
{
if (*paused_topic)
help_show_paused_topic(paused_topic, empty_string);
return;
}
if (line && toupper(*line) == 'Q')
{
finished_help_paging = 1;
#if 0
help_paused_lines = 0;
#endif
fclose(help_fp);
help_fp = NULL;
set_help_screen((Screen *) 0);
return;
}
if (show_help(help_window, name))
{
if (dumb_mode)
help_prompt(name, NULL);
else
add_wait_prompt("*** Hit any key for more, 'q' to quit ***",
help_prompt, name, WAIT_PROMPT_KEY, 1);
}
else
{
finished_help_paging = 1;
if (help_fp)
fclose(help_fp);
help_fp = NULL;
if (help_show_directory)
{
if (get_int_var(HELP_PAGER_VAR))
{
if (dumb_mode)
help_show_paused_topic(name, empty_string);
else
add_wait_prompt("*** Hit any key to end ***",
help_show_paused_topic, paused_topic,
WAIT_PROMPT_KEY, 1);
}
else
{
help_show_paused_topic(paused_topic, empty_string);
set_help_screen((Screen *) 0);
}
help_show_directory = 0;
return;
}
}
if (finished_help_paging)
{
if (get_int_var(HELP_PROMPT_VAR))
{
char tmp[BIG_BUFFER_SIZE + 1];
sprintf(tmp, "%s%sHelp? ", help_topic_list,
*help_topic_list ? space : empty_string);
if (!dumb_mode)
add_wait_prompt(tmp, help_me, help_topic_list,
WAIT_PROMPT_LINE, 1);
}
else
{
if (*paused_topic)
help_show_paused_topic(paused_topic, empty_string);
set_help_screen((Screen *) 0);
}
}
}
static void help_topic (char *path, char *name)
{
char *filename = NULL;
if (!name)
return;
filename = m_sprintf("%s/%s", path, name);
if (filename[strlen(filename)-1] == '/')
chop(filename, 1);
if ((help_fp = uzfopen (&filename, path, 0)))
{
help_put_it(name, "*** Help on %s", name);
help_prompt(name, NULL);
}
else
help_put_it (name, "*** No help available on %s: Use ? for list of topics", name);
new_free(&filename);
return;
}
static void help_pause_add_line (char *format, ...)
{
char buf[BIG_BUFFER_SIZE];
va_list args;
va_start (args, format);
vsnprintf(buf, BIG_BUFFER_SIZE - 1, format, args);
va_end (args);
if ((help_paused_lines + 1) >= HELP_PAUSED_LINES_MAX)
ircpanic("help_pause_add_line: would overflow the buffer");
malloc_strcpy(&help_paused_topic[help_paused_lines++], buf);
}
static void help_show_paused_topic (char *name, char *line)
{
static int i = 0;
int j = 0;
int rows;
if (!help_paused_lines)
return;
if (toupper(*line) == 'Q')
i = help_paused_lines + 1;
rows = help_window->display_size;
if (i < help_paused_lines)
{
for (j = 0; j < rows; j++)
{
help_put_it (name, "%s", help_paused_topic[i]);
new_free(&help_paused_topic[i]);
if (++i >= help_paused_lines)
break;
}
if (!dumb_mode)
{
if ((i < help_paused_lines) && get_int_var(HELP_PAGER_VAR))
add_wait_prompt("[MORE]", help_show_paused_topic, name, WAIT_PROMPT_KEY, 1);
}
else
help_show_paused_topic(name, line);
}
if (i >= help_paused_lines)
{
if (get_int_var(HELP_PROMPT_VAR))
{
char buf[BIG_BUFFER_SIZE];
sprintf(buf, "%s%sHelp? ", name, (name && *name) ? space : empty_string);
if (!dumb_mode)
add_wait_prompt(buf, help_me, name, WAIT_PROMPT_LINE, 1);
}
else
set_help_screen((Screen *) 0);
dont_pause_topic = 0;
help_paused_lines = 0;
i = 0;
}
}
static void help_me (char *topics, char *args)
{
char * ptr;
glob_t g;
int entries = 0,
cnt,
i,
cols;
struct stat stat_buf;
char path[BIG_BUFFER_SIZE+1];
int help_paused_first_call = 0;
char * help_paused_path = (char *) 0;
char * help_paused_name = (char *) 0;
char * temp;
char tmp[BIG_BUFFER_SIZE+1];
char buffer[BIG_BUFFER_SIZE+1];
char * pattern = NULL;
strcpy(help_topic_list, topics);
ptr = get_string_var(HELP_PATH_VAR);
sprintf(path, "%s/%s", ptr, topics);
for (ptr = path; (ptr = strchr(ptr, ' '));)
*ptr = '/';
if (help_show_directory)
{
help_show_paused_topic(paused_topic, empty_string);
help_show_directory = 0;
}
finished_help_paging = 0;
if (access(path, R_OK|X_OK))
{
help_put_it(no_help, "*** Cannot access help directory!");
set_help_screen((Screen *) 0);
return;
}
this_arg = next_arg(args, &args);
if (!this_arg && *help_topic_list && get_int_var(HELP_PROMPT_VAR))
{
if ((temp = strrchr(help_topic_list, ' ')) != NULL)
*temp = '\0';
else
*help_topic_list = '\0';
sprintf(tmp, "%s%sHelp? ", help_topic_list, *help_topic_list ? space : empty_string);
if (!dumb_mode)
add_wait_prompt(tmp, help_me, help_topic_list, WAIT_PROMPT_LINE, 1);
return;
}
if (!this_arg)
{
set_help_screen((Screen *) 0);
return;
}
create_help_window();
while (this_arg)
{
entries = 0;
reset_display_target();
if (!*this_arg)
help_topic(path, NULL);
if (strcmp(this_arg, "?") == 0)
{
this_arg = empty_string;
if (!dont_pause_topic)
dont_pause_topic = 1;
}
entry_size = 0;
{
#ifndef HAVE_FCHDIR
char opath[MAXPATHLEN + 1];
getcwd(opath, MAXPATHLEN);
#else
int cwd = open(".", O_RDONLY);
#endif
chdir(path);
pattern = alloca(strlen(path) + 2 +
strlen(this_arg) + 3);
strcpy(pattern, this_arg);
strcat(pattern, "*");
#ifdef GLOB_INSENSITIVE
bsd_glob(pattern, GLOB_INSENSITIVE , NULL, &g);
#else
bsd_glob(pattern, 0 , NULL, &g);
#endif
#ifndef HAVE_FCHDIR
chdir(opath);
#else
fchdir(cwd);
close(cwd);
#endif
}
for (i = 0; i < g.gl_matchc; i++)
{
char *tmp = g.gl_pathv[i];
int len = strlen(tmp);
if (!end_strcmp(tmp, ".gz", 3))
len -= 3;
else if (!end_strcmp(tmp, ".bz2", 4))
len -= 4;
entry_size = (len > entry_size) ? len : entry_size;
}
if (g.gl_matchc > 1)
{
char *str1 = g.gl_pathv[0];
char *str2 = this_arg;
int len1 = strlen(str1);
int len2 = strlen(str2);
if (len1 == len2 && !my_stricmp(str1, str2))
entries = 1;
else if (len1 - 3 == len2 && !my_strnicmp(str1, str2, len2) && !end_strcmp(str1, ".gz", 3))
entries = 1;
else if (len1 - 2 == len2 && !my_strnicmp(str1, str2, len2) && !end_strcmp(str1, ".Z", 2))
entries = 1;
else if (len1 - 2 == len2 && !my_strnicmp(str1, str2, len2) && !end_strcmp(str1, ".z", 2))
entries = 1;
}
if (!*help_topic_list)
dont_pause_topic = 1;
if (!entries)
entries = g.gl_matchc;
switch (entries)
{
case -1:
{
help_put_it(no_help, "*** Error during help function: %s", strerror(errno));
set_help_screen(NULL);
if (help_paused_first_call)
{
help_topic(help_paused_path, help_paused_name);
help_paused_first_call = 0;
new_free(&help_paused_path);
new_free(&help_paused_name);
}
return;
}
case 0:
{
help_put_it(this_arg, "*** No help available on %s: Use ? for list of topics", this_arg);
if (!get_int_var(HELP_PROMPT_VAR))
{
set_help_screen(NULL);
break;
}
sprintf(tmp, "%s%sHelp? ", help_topic_list, *help_topic_list ? space : empty_string);
if (!dumb_mode)
add_wait_prompt(tmp, help_me, help_topic_list, WAIT_PROMPT_LINE, 1);
if (help_paused_first_call)
{
help_topic(help_paused_path, help_paused_name);
help_paused_first_call = 0;
new_free(&help_paused_path);
new_free(&help_paused_name);
}
break;
}
case 1:
{
sprintf(tmp, "%s/%s", path, g.gl_pathv[0]);
stat(tmp, &stat_buf);
if (stat_buf.st_mode & S_IFDIR)
{
strcpy(path, tmp);
if (*help_topic_list)
strcat(help_topic_list, space);
strcat(help_topic_list, g.gl_pathv[0]);
if (!(this_arg = next_arg(args, &args)))
{
help_paused_first_call = 1;
malloc_strcpy(&help_paused_path, path);
malloc_strcpy(&help_paused_name, g.gl_pathv[0]);
dont_pause_topic = -1;
this_arg = "?";
}
bsd_globfree(&g);
continue;
}
else
{
help_topic(path, g.gl_pathv[0]);
finished_help_paging = 0;
break;
}
}
default:
{
help_show_directory = 1;
strcpy(paused_topic, help_topic_list);
help_pause_add_line("*** %s choices:", help_topic_list);
entry_size += 2;
cols = (current_term->TI_cols - 10) / entry_size;
strcpy(buffer, empty_string);
cnt = 0;
for (i = 0; i < entries; i++)
{
if (!end_strcmp(g.gl_pathv[i], ".gz", 3))
chop(g.gl_pathv[i], 3);
else if (!end_strcmp(g.gl_pathv[i], ".bz2", 4))
chop(g.gl_pathv[i], 4);
strcat(buffer, g.gl_pathv[i]);
if (++cnt == cols)
{
help_pause_add_line("%s", buffer);
strcpy(buffer, empty_string);
cnt = 0;
}
else
strextend(buffer, ' ', entry_size - strlen(g.gl_pathv[i]));
}
help_pause_add_line("%s", buffer);
if (help_paused_first_call)
{
help_topic(help_paused_path, help_paused_name);
help_paused_first_call = 0;
new_free(&help_paused_path);
new_free(&help_paused_name);
}
if (dont_pause_topic == 1)
{
help_show_paused_topic(paused_topic, empty_string);
help_show_directory = 0;
}
break;
}
}
bsd_globfree(&g);
break;
}
if (!*help_topic_list && finished_help_paging)
set_help_screen((Screen *) 0);
}
BUILT_IN_COMMAND(epichelp)
{
char *help_path;
finished_help_paging = 0;
help_show_directory = 0;
dont_pause_topic = 0;
use_help_window = 0;
help_path = get_string_var(HELP_PATH_VAR);
if (!help_path || !*help_path || access(help_path, R_OK | X_OK))
{
help_put_it(no_help, "*** HELP_PATH variable not set or set to an invalid path");
return;
}
if (!my_strnicmp(args, "-wait", 2))
{
while (help_screen)
io("help");
return;
}
if (help_path && help_screen && help_screen != current_window->screen)
{
say("You may not run help in two screens");
return;
}
help_screen = current_window->screen;
help_window = (Window *) 0;
help_me(empty_string, (args && *args) ? args : "?");
}
static void create_help_window (void)
{
if (help_window)
return;
if (!dumb_mode && get_int_var(HELP_WINDOW_VAR))
{
use_help_window = 1;
help_window = new_window(current_window->screen);
help_window->hold_mode = OFF;
help_window->window_level = LOG_HELP;
update_all_windows();
}
else
help_window = current_window;
}
static void set_help_screen (Screen *screen)
{
help_screen = screen;
if (!help_screen && help_window)
{
if (use_help_window)
{
int display = window_display;
window_display = 0;
delete_window(help_window);
window_display = display;
}
help_window = (Window *) 0;
update_all_windows();
}
}
static void help_put_it (const char *topic, const char *format, ...)
{
char putbuf[BIG_BUFFER_SIZE * 3 + 1];
if (format)
{
va_list args;
va_start (args, format);
vsnprintf(putbuf, BIG_BUFFER_SIZE * 3, format, args);
va_end(args);
if (do_hook(HELP_LIST, "%s %s", topic, putbuf))
{
int old_level = who_level;
Window *old_target_window = target_window;
who_level = LOG_HELP;
if (help_window)
target_window = help_window;
add_to_screen(putbuf);
target_window = old_target_window;
who_level = old_level;
}
}
}
#endif