#include <errno.h>
#include <stdarg.h>
#include "citadel.h"
+#include "citadel_ipc.h"
#include "commands.h"
#include "messages.h"
#include "citadel_decls.h"
#include "tools.h"
#include "rooms.h"
#include "client_chat.h"
+#include "citadel_dirs.h"
#ifndef HAVE_SNPRINTF
#include "snprintf.h"
#endif
+#include "screen.h"
struct citcmd {
struct citcmd *next;
int rc_force_mail_prompts;
int rc_remember_passwords;
int rc_ansi_color;
-int num_urls = 0;
-char urls[MAXURLS][SIZ];
+int rc_color_use_bg;
+int rc_prompt_control = 0;
+time_t rc_idle_threshold = (time_t)900;
char rc_url_cmd[SIZ];
+char rc_gotmail_cmd[SIZ];
char *gl_string;
int next_lazy_cmd = 5;
int lines_printed = 0; /* line count for paginator */
extern int screenwidth, screenheight;
extern int termn8;
+extern CtdlIPC *ipc_for_signal_handlers; /* KLUDGE cover your eyes */
struct citcmd *cmdlist = NULL;
/* these variables are local to this module */
char keepalives_enabled = KA_YES; /* send NOOPs to server when idle */
-int ok_to_interrupt = 0; /* print express msgs asynchronously */
+int ok_to_interrupt = 0; /* print instant msgs asynchronously */
time_t AnsiDetect; /* when did we send the detect code? */
int enable_color = 0; /* nonzero for ANSI color */
/*
* Check to see if we need to pause at the end of a screen.
- * If we do, we have to disable server keepalives during the pause because
+ * If we do, we have to switch to half keepalives during the pause because
* we are probably in the middle of a server operation and the NOOP command
* would confuse everything.
*/
-int checkpagin(int lp, int pagin, int height)
+int checkpagin(int lp, unsigned int pagin, unsigned int height)
{
int thekey;
if (sigcaught) return(lp);
thekey = was_a_key_pressed();
+ if (thekey == 'q' || thekey == 'Q' || thekey == 's' || thekey == 'S')
+ thekey = STOP_KEY;
+ if (thekey == 'n' || thekey == 'N')
+ thekey = NEXT_KEY;
if ( (thekey == NEXT_KEY) || (thekey == STOP_KEY)) sigcaught = thekey;
if (sigcaught) return(lp);
if (!pagin) return(0);
if (lp>=(height-1)) {
- set_keepalives(KA_NO);
- hit_any_key();
+ set_keepalives(KA_HALF);
+ hit_any_key(ipc_for_signal_handlers); /* Cheating -IO */
set_keepalives(KA_YES);
return(0);
}
/* Otherwise, start spewing... */
va_start(arg_ptr, format);
- vsprintf(buf, format, arg_ptr);
+ vsnprintf(buf, sizeof(buf), format, arg_ptr);
va_end(arg_ptr);
- for (i=0; i<strlen(buf); ++i) {
- putc(buf[i], stdout);
+ for (i=0; !IsEmptyStr(&buf[i]); ++i) {
+ scr_putc(buf[i]);
if (buf[i]==10) {
++lines_printed;
lines_printed = checkpagin(lines_printed,
/*
- * print_express() - print express messages if there are any
+ * print_instant() - print instant messages if there are any
*/
-void print_express(void)
+void print_instant(void)
{
char buf[1024];
FILE *outpipe;
time_t timestamp;
- struct tm *stamp;
+ struct tm stamp;
int flags = 0;
char sender[64];
char node[64];
+ char *listing = NULL;
+ int r; /* IPC result code */
- if (express_msgs == 0)
+ if (instant_msgs == 0)
return;
if (rc_exp_beep) {
- putc(7, stdout);
+ ctdl_beep();
}
- if (strlen(rc_exp_cmd) == 0) {
+ if (IsEmptyStr(rc_exp_cmd)) {
color(BRIGHT_RED);
- printf("\r---");
+ scr_printf("\r---");
}
- while (express_msgs != 0) {
- serv_puts("GEXP");
- serv_gets(buf);
- if (buf[0] != '1')
+ while (instant_msgs != 0) {
+ r = CtdlIPCGetInstantMessage(ipc_for_signal_handlers, &listing, buf);
+ if (r / 100 != 1)
return;
- express_msgs = extract_int(&buf[4], 0);
- timestamp = extract_long(&buf[4], 1);
- flags = extract_int(&buf[4], 2);
- extract(sender, &buf[4], 3);
- extract(node, &buf[4], 4);
+ instant_msgs = extract_int(buf, 0);
+ timestamp = extract_long(buf, 1);
+ flags = extract_int(buf, 2);
+ extract_token(sender, buf, 3, '|', sizeof sender);
+ extract_token(node, buf, 4, '|', sizeof node);
strcpy(last_paged, sender);
- stamp = localtime(×tamp);
+ localtime_r(×tamp, &stamp);
/* If the page is a Logoff Request, honor it. */
if (flags & 2) {
return;
}
- if (strlen(rc_exp_cmd) > 0) {
+ if (!IsEmptyStr(rc_exp_cmd)) {
outpipe = popen(rc_exp_cmd, "w");
if (outpipe != NULL) {
/* Header derived from flags */
else
fprintf(outpipe, "Message ");
/* Timestamp. Can this be improved? */
- if (stamp->tm_hour == 0 || stamp->tm_hour == 12)
+ if (stamp.tm_hour == 0 || stamp.tm_hour == 12)
fprintf(outpipe, "at 12:%02d%cm",
- stamp->tm_min,
- stamp->tm_hour ? 'p' : 'a');
- else if (stamp->tm_hour > 12) /* pm */
+ stamp.tm_min,
+ stamp.tm_hour ? 'p' : 'a');
+ else if (stamp.tm_hour > 12) /* pm */
fprintf(outpipe, "at %d:%02dpm",
- stamp->tm_hour - 12,
- stamp->tm_min);
+ stamp.tm_hour - 12,
+ stamp.tm_min);
else /* am */
fprintf(outpipe, "at %d:%02dam",
- stamp->tm_hour, stamp->tm_min);
+ stamp.tm_hour, stamp.tm_min);
fprintf(outpipe, " from %s", sender);
- if (strncmp(serv_info.serv_nodename, node, 32))
+ if (strncmp(ipc_for_signal_handlers->ServInfo.nodename, node, 32))
fprintf(outpipe, " @%s", node);
- fprintf(outpipe, ":\n");
- while (serv_gets(buf), strcmp(buf, "000")) {
- fprintf(outpipe, "%s\n", buf);
- }
+ fprintf(outpipe, ":\n%s\n", listing);
pclose(outpipe);
- if (express_msgs == 0)
+ if (instant_msgs == 0)
return;
continue;
}
}
- /* fall back to built-in express message display */
- printf("\n");
+ /* fall back to built-in instant message display */
+ scr_printf("\n");
+ lines_printed++;
/* Header derived from flags */
if (flags & 2)
- printf("Please log off now, as requested ");
+ scr_printf("Please log off now, as requested ");
else if (flags & 1)
- printf("Broadcast message ");
+ scr_printf("Broadcast message ");
else if (flags & 4)
- printf("Chat request ");
+ scr_printf("Chat request ");
else
- printf("Message ");
+ scr_printf("Message ");
/* Timestamp. Can this be improved? */
- if (stamp->tm_hour == 0 || stamp->tm_hour == 12)/* 12am/12pm */
- printf("at 12:%02d%cm", stamp->tm_min,
- stamp->tm_hour ? 'p' : 'a');
- else if (stamp->tm_hour > 12) /* pm */
- printf("at %d:%02dpm",
- stamp->tm_hour - 12, stamp->tm_min);
+ if (stamp.tm_hour == 0 || stamp.tm_hour == 12)/* 12am/12pm */
+ scr_printf("at 12:%02d%cm", stamp.tm_min,
+ stamp.tm_hour ? 'p' : 'a');
+ else if (stamp.tm_hour > 12) /* pm */
+ scr_printf("at %d:%02dpm",
+ stamp.tm_hour - 12, stamp.tm_min);
else /* am */
- printf("at %d:%02dam", stamp->tm_hour, stamp->tm_min);
+ scr_printf("at %d:%02dam", stamp.tm_hour, stamp.tm_min);
/* Sender */
- printf(" from %s", sender);
+ scr_printf(" from %s", sender);
/* Remote node, if any */
- if (strncmp(serv_info.serv_nodename, node, 32))
- printf(" @%s", node);
+ if (strncmp(ipc_for_signal_handlers->ServInfo.nodename, node, 32))
+ scr_printf(" @%s", node);
- printf(":\n");
-
- while (serv_gets(buf), strcmp(buf, "000")) {
- printf("%s", buf);
- }
+ scr_printf(":\n");
+ lines_printed++;
+ fmout(screenwidth, NULL, listing, NULL, 1, screenheight, -1, 0);
+ free(listing);
+
+ /* when running in curses mode, the scroll bar in most
+ xterm-style programs becomes useless, so it makes sense to
+ pause after a screenful of pages if the user has been idle
+ for a while. However, this is annoying to some of the users
+ who aren't in curses mode and tend to leave their clients
+ idle. keepalives become disabled, resulting in getting booted
+ when coming back to the idle session. but they probably have
+ a working scrollback in their terminal, so disable it in this
+ case:
+ */
+ if (!is_curses_enabled())
+ lines_printed = 0;
}
- printf("\n---\n");
+ scr_printf("\n---\n");
color(BRIGHT_WHITE);
static time_t idlet = 0;
static void really_do_keepalive(void) {
- char buf[1024];
+ int r; /* IPC response code */
time(&idlet);
+
+ /* This may sometimes get called before we are actually connected
+ * to the server. Don't do anything if we aren't connected. -IO
+ */
+ if (!ipc_for_signal_handlers)
+ return;
+
+ /* If full keepalives are enabled, send a NOOP to the server and
+ * wait for a response.
+ */
if (keepalives_enabled == KA_YES) {
- serv_puts("NOOP");
- serv_gets(buf);
- if (buf[3] == '*') {
- express_msgs = 1;
+ r = CtdlIPCNoop(ipc_for_signal_handlers);
+ if (instant_msgs > 0) {
if (ok_to_interrupt == 1) {
- printf("\r%64s\r", "");
- print_express();
- printf("%s%c ", room_name,
+ scr_printf("\r%64s\r", "");
+ print_instant();
+ scr_printf("%s%c ", room_name,
room_prompt(room_flags));
- fflush(stdout);
+ scr_flush();
}
}
}
+
+ /* If half keepalives are enabled, send a QNOP to the server (if the
+ * server supports it) and then do nothing.
+ */
+ if ( (keepalives_enabled == KA_HALF)
+ && (ipc_for_signal_handlers->ServInfo.supports_qnop > 0) ) {
+ CtdlIPC_chat_send(ipc_for_signal_handlers, "QNOP");
+ }
}
/* threaded nonblocking keepalive stuff starts here. I'm going for a simple
}
#endif /* THREADED_CLIENT */
-static void do_keepalive(void)
+/* I changed this from static to not because I need to call it from
+ screen.c, either that or make something in screen.c not static.
+ Fix it how you like. Why all the staticness? stu */
+
+void do_keepalive(void)
{
time_t now;
return;
/* Do a space-backspace to keep telnet sessions from idling out */
- printf(" %c", 8);
- fflush(stdout);
+ scr_printf(" %c", 8);
+ scr_flush();
#ifdef THREADED_CLIENT
if (async_ka_enabled)
int a; /* the watchdog timer in effect if necessary */
fd_set rfds;
struct timeval tv;
- time_t start_time, now;
- char inbuf[2];
+ time_t start_time;
- fflush(stdout);
+ scr_flush();
lines_printed = 0;
time(&start_time);
do {
-
/* This loop waits for keyboard input. If the keepalive
* timer expires, it sends a keepalive to the server if
* necessary and then waits again.
*/
do {
+ scr_set_windowsize(ipc_for_signal_handlers);
do_keepalive();
+ scr_set_windowsize(ipc_for_signal_handlers);
FD_ZERO(&rfds);
FD_SET(0, &rfds);
tv.tv_sec = S_KEEPALIVE;
tv.tv_usec = 0;
- time(&now);
- if (((now - start_time) > SLEEPING)
- && (SLEEPING != 0) && (getppid() == 1)) {
- printf("Sleeping? Call again.\n");
- logoff(SIGALRM);
- }
select(1, &rfds, NULL, NULL, &tv);
} while (!FD_ISSET(0, &rfds));
-
-
-
/* At this point, there's input, so fetch it.
* (There's a hole in the bucket...)
*/
- read(0, inbuf, 1);
- a = inbuf[0];
- if (a == 127)
+ a = scr_getc(SCR_BLOCK);
+ if (a == 127) {
a = 8;
- if (a > 126)
+ }
+ if (a == 13) {
+ a = 10;
+ }
+/* not so fast there dude, we have to handle UTF-8 and ISO-8859-1...
+ if (a > 126) {
a = 0;
- if (a == 10)
- a = 13;
- if (((a != 4) && (a != 13) && (a != 8) && (a != NEXT_KEY) && (a != STOP_KEY))
- && ((a < 32) || (a > 126)))
+ }
+ if (((a != 23) && (a != 4) && (a != 10) && (a != 8) && (a != NEXT_KEY) && (a != STOP_KEY))
+ && ((a < 32) || (a > 126))) {
a = 0;
+ }
+ */
+
+#ifndef DISABLE_CURSES
+#if defined(HAVE_CURSES_H) || defined(HAVE_NCURSES_H)
+ if (a == ERR) {
+ logoff(NULL, 3);
+ }
+#endif
+#endif
+
} while (a == 0);
return (a);
}
a = inkey();
a = tolower(a);
if (a == 'y') {
- printf("Yes\n");
+ scr_printf("Yes\n");
return (1);
}
if (a == 'n') {
- printf("No\n");
+ scr_printf("No\n");
return (0);
}
}
while (1) {
a = inkey();
a = tolower(a);
- if (a == 13)
+ if (a == 10)
a = (d ? 'y' : 'n');
if (a == 'y') {
- printf("Yes\n");
+ scr_printf("Yes\n");
return (1);
}
if (a == 'n') {
- printf("No\n");
+ scr_printf("No\n");
return (0);
}
}
/* Gets a line from the terminal */
/* string == Pointer to string buffer */
/* lim == Maximum length - if negative, no-show */
-void getline(char *string, int lim)
+void ctdl_getline(char *string, int lim)
{
int a, b;
char flag = 0;
strcpy(string, "");
gl_string = string;
async_ka_start();
- GLA:a = inkey();
- a = (a & 127);
- if ((a == 8) && (strlen(string) == 0))
+
+GLA: a = inkey();
+ /* a = (a & 127); ** commented out because it isn't just an ASCII world anymore */
+ if ((a == 8 || a == 23) && (IsEmptyStr(string)))
goto GLA;
- if ((a != 13) && (a != 8) && (strlen(string) == lim))
+ if ((a != 10) && (a != 8) && (strlen(string) == lim))
goto GLA;
if ((a == 8) && (string[0] != 0)) {
string[strlen(string) - 1] = 0;
- putc(8, stdout);
- putc(32, stdout);
- putc(8, stdout);
+ scr_putc(8); scr_putc(32); scr_putc(8);
+ goto GLA;
+ }
+ if ((a == 23) && (string[0] != 0)) {
+ do {
+ string[strlen(string) - 1] = 0;
+ scr_putc(8); scr_putc(32); scr_putc(8);
+ } while (!IsEmptyStr(string) && string[strlen(string) - 1] != ' ');
goto GLA;
}
- if ((a == 13) || (a == 10)) {
- putc(13, stdout);
- putc(10, stdout);
+ if ((a == 10)) {
+ scr_putc(10);
async_ka_end();
return;
}
string[b] = a;
string[b + 1] = 0;
if (flag == 0)
- putc(a, stdout);
+ scr_putc(a);
if (flag == 1)
- putc('*', stdout);
+ scr_putc('*');
goto GLA;
}
*/
void strprompt(char *prompt, char *str, int len)
{
+ int i;
char buf[128];
- print_express();
+
+ print_instant();
color(DIM_WHITE);
- printf("%s ", prompt);
+ scr_printf("%s ", prompt);
color(DIM_MAGENTA);
- printf("[");
+ scr_printf("[");
color(BRIGHT_MAGENTA);
- printf("%s", str);
+
+ if (len >= 0) {
+ scr_printf("%s", str);
+ }
+ else {
+ for (i=0; !IsEmptyStr(&str[i]); ++i) {
+ scr_printf("*");
+ }
+ }
+
color(DIM_MAGENTA);
- printf("]");
+ scr_printf("]");
color(DIM_WHITE);
- printf(": ");
+ scr_printf(": ");
color(BRIGHT_CYAN);
- getline(buf, len);
+ ctdl_getline(buf, len);
if (buf[0] != 0)
strcpy(str, buf);
color(DIM_WHITE);
int r;
color(DIM_WHITE);
- printf("%s ", prompt);
+ scr_printf("%s ", prompt);
color(DIM_MAGENTA);
- printf(" [");
+ scr_printf("[");
color(BRIGHT_MAGENTA);
- printf("%s", (prev_val ? "Yes" : "No"));
+ scr_printf("%s", (prev_val ? "Yes" : "No"));
color(DIM_MAGENTA);
- printf("]: ");
+ scr_printf("]: ");
color(BRIGHT_CYAN);
r = (yesno_d(prev_val));
color(DIM_WHITE);
snprintf(buf, sizeof buf, "%d", i);
strprompt(prompt, buf, 15);
i = atoi(buf);
- for (p=0; p<strlen(buf); ++p) {
+ for (p=0; !IsEmptyStr(&buf[p]); ++p) {
if ( (!isdigit(buf[p]))
&& ( (buf[p]!='-') || (p!=0) ) )
i = imin - 1;
}
if (i < imin)
- printf("*** Must be no less than %d.\n", imin);
+ scr_printf("*** Must be no less than %d.\n", imin);
if (i > imax)
- printf("*** Must be no more than %d.\n", imax);
+ scr_printf("*** Must be no more than %d.\n", imax);
} while ((i < imin) || (i > imax));
return (i);
}
void newprompt(char *prompt, char *str, int len)
{
color(BRIGHT_MAGENTA);
- printf("%s", prompt);
+ scr_printf("%s", prompt);
color(DIM_MAGENTA);
- getline(str, len);
+ ctdl_getline(str, len);
color(DIM_WHITE);
}
{
FILE *ccfile;
char buf[1024];
+ char editor_key[100];
struct citcmd *cptr;
struct citcmd *lastcmd = NULL;
int a, d;
int b = 0;
+ int i;
/* first, set up some defaults for non-required variables */
- strcpy(editor_path, "");
+ for (i = 0; i < MAX_EDITORS; i++)
+ strcpy(editor_paths[i], "");
strcpy(printcmd, "");
+ strcpy(imagecmd, "");
strcpy(rc_username, "");
strcpy(rc_password, "");
rc_floor_mode = 0;
rc_display_message_numbers = 0;
rc_force_mail_prompts = 0;
rc_ansi_color = 0;
+ rc_color_use_bg = 0;
strcpy(rc_url_cmd, "");
+ strcpy(rc_gotmail_cmd, "");
+#ifdef HAVE_OPENSSL
+ rc_encrypt = RC_DEFAULT;
+#endif
+#if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
+ rc_screen = RC_DEFAULT;
+#endif
+ rc_alt_semantics = 0;
/* now try to open the citadel.rc file */
ccfile = fopen(buf, "r");
}
if (ccfile == NULL) {
- ccfile = fopen("/usr/local/lib/citadel.rc", "r");
+ ccfile = fopen(file_citadel_rc, "r");
}
if (ccfile == NULL) {
- snprintf(buf, sizeof buf, "%s/citadel.rc", BBSDIR);
- ccfile = fopen(buf, "r");
+ ccfile = fopen("/etc/citadel.rc", "r");
}
if (ccfile == NULL) {
ccfile = fopen("./citadel.rc", "r");
}
if (ccfile == NULL) {
perror("commands: cannot open citadel.rc");
- logoff(errno);
+ logoff(NULL, 3);
}
while (fgets(buf, sizeof buf, ccfile) != NULL) {
- while ((strlen(buf) > 0) ? (isspace(buf[strlen(buf) - 1])) : 0)
+ while ((!IsEmptyStr(buf)) ? (isspace(buf[strlen(buf) - 1])) : 0)
buf[strlen(buf) - 1] = 0;
+ if (!strncasecmp(buf, "encrypt=", 8)) {
+ if (!strcasecmp(&buf[8], "yes")) {
+#ifdef HAVE_OPENSSL
+ rc_encrypt = RC_YES;
+#else
+ fprintf(stderr, "citadel.rc requires encryption support but citadel is not compiled with OpenSSL");
+ logoff(NULL, 3);
+#endif
+ }
+#ifdef HAVE_OPENSSL
+ else if (!strcasecmp(&buf[8], "no")) {
+ rc_encrypt = RC_NO;
+ }
+ else if (!strcasecmp(&buf[8], "default")) {
+ rc_encrypt = RC_DEFAULT;
+ }
+#endif
+ }
+
+#if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
+ if (!strncasecmp(buf, "fullscreen=", 11)) {
+ if (!strcasecmp(&buf[11], "yes"))
+ rc_screen = RC_YES;
+ else if (!strcasecmp(&buf[11], "no"))
+ rc_screen = RC_NO;
+ }
+#endif
+
if (!strncasecmp(buf, "editor=", 7))
- strcpy(editor_path, &buf[7]);
+ strcpy(editor_paths[0], &buf[7]);
+
+ for (i = 0; i < MAX_EDITORS; i++)
+ {
+ sprintf(editor_key, "editor%d=", i);
+ if (!strncasecmp(buf, editor_key, strlen(editor_key)))
+ strcpy(editor_paths[i], &buf[strlen(editor_key)]);
+ }
if (!strncasecmp(buf, "printcmd=", 9))
strcpy(printcmd, &buf[9]);
+ if (!strncasecmp(buf, "imagecmd=", 9))
+ strcpy(imagecmd, &buf[9]);
+
if (!strncasecmp(buf, "expcmd=", 7))
strcpy(rc_exp_cmd, &buf[7]);
if (!strncasecmp(buf, "allow_attachments=", 18)) {
rc_allow_attachments = atoi(&buf[18]);
}
+ if (!strncasecmp(buf, "idle_threshold=", 15)) {
+ rc_idle_threshold = atol(&buf[15]);
+ }
if (!strncasecmp(buf, "remember_passwords=", 19)) {
rc_remember_passwords = atoi(&buf[19]);
}
if (!strncasecmp(&buf[11], "user", 4))
rc_ansi_color = 3; /* user config */
}
+ if (!strncasecmp(buf, "use_background=", 15)) {
+ if (!strncasecmp(&buf[15], "on", 2))
+ rc_color_use_bg = 9;
+ }
+ if (!strncasecmp(buf, "prompt_control=", 15)) {
+ if (!strncasecmp(&buf[15], "on", 2))
+ rc_prompt_control = 1;
+ if (!strncasecmp(&buf[15], "user", 4))
+ rc_prompt_control = 3; /* user config */
+ }
if (!strncasecmp(buf, "username=", 9))
strcpy(rc_username, &buf[9]);
if (!strncasecmp(buf, "urlcmd=", 7))
strcpy(rc_url_cmd, &buf[7]);
+ if (!strncasecmp(buf, "gotmailcmd=", 11))
+ strcpy(rc_gotmail_cmd, &buf[11]);
+
+ if (!strncasecmp(buf, "alternate_semantics=", 20)) {
+ if (!strncasecmp(&buf[20], "yes", 3)) {
+ rc_alt_semantics = 1;
+ }
+ else {
+ rc_alt_semantics = 0;
+ }
+ }
+
if (!strncasecmp(buf, "cmd=", 4)) {
strcpy(buf, &buf[4]);
a = 0;
b = 0;
buf[strlen(buf) + 1] = 0;
- while (strlen(buf) > 0) {
+ while (!IsEmptyStr(buf)) {
b = strlen(buf);
for (d = strlen(buf); d >= 0; --d)
if (buf[d] == ',')
{
int a;
- for (a = 0; a < strlen(cmdstr); ++a)
+ for (a = 0; !IsEmptyStr(&cmdstr[a]); ++a)
if (cmdstr[a] == '&')
return (tolower(cmdstr[a + 1]));
return (0);
int a;
static char exp[64];
char buf[1024];
+ char *ptr;
strcpy(exp, strbuf);
- for (a = 0; a < strlen(exp); ++a) {
- if (strbuf[a] == '&') {
+ ptr = exp;
+ while (!IsEmptyStr(ptr)){
+ if (*ptr == '&') {
+
+ /* dont echo these non mnemonic command keys */
+ int noecho = *(ptr+1) == '<' || *(ptr+1) == '>' ||
+ *(ptr+1) == '+' || *(ptr+1) == '-';
if (mode == 0) {
- strcpy(&exp[a], &exp[a + 1]);
+ strcpy(ptr, ptr + 1 + noecho);
}
if (mode == 1) {
- exp[a] = '<';
- strcpy(buf, &exp[a + 2]);
- exp[a + 2] = '>';
- exp[a + 3] = 0;
+ *ptr = '<';
+ strcpy(buf, ptr + 2);
+ *(ptr + 2) = '>';
+ *(ptr+ 3) = 0;
strcat(exp, buf);
}
}
- if (!strncmp(&exp[a], "^r", 2)) {
+ if (!strncmp(ptr, "^r", 2)) {
strcpy(buf, exp);
- strcpy(&exp[a], room_name);
- strcat(exp, &buf[a + 2]);
+ strcpy(ptr, room_name);
+ strcat(exp, &buf[ptr - exp + 2]);
}
- if (!strncmp(&exp[a], "^c", 2)) {
- exp[a] = ',';
- strcpy(&exp[a + 1], &exp[a + 2]);
+ if (!strncmp(ptr, "^c", 2)) {
+ *ptr = ',';
+ strcpy(ptr + 1], ptr + 2]);
}
}
char buf[64];
strcpy(buf, cptr->c_keys[ncomp - 1]);
- for (a = 0; a < strlen(buf); ++a) {
+ for (a = 0; !IsEmptyStr(&buf[a]); ++a) {
if (buf[a] == ':')
return (1);
}
* This function returns an integer command number. If the command prompts
* for a string then it is placed in the supplied buffer.
*/
-int getcmd(char *argbuf)
+int getcmd(CtdlIPC *ipc, char *argbuf)
{
char cmdbuf[5];
int cmdspaces[5];
enable_color = 0;
}
/* if we're running in idiot mode, display a cute little menu */
- IFNEXPERT formout("mainmenu");
+ IFNEXPERT formout(ipc, "mainmenu");
- print_express(); /* print express messages if there are any */
+ print_instant();
strcpy(argbuf, "");
cmdpos = 0;
for (a = 0; a < 5; ++a)
/* now the room prompt... */
ok_to_interrupt = 1;
color(BRIGHT_WHITE);
- printf("\n%s", room_name);
+ scr_printf("\n%s", room_name);
color(DIM_WHITE);
- printf("%c ", room_prompt(room_flags));
- fflush(stdout);
+ scr_printf("%c ", room_prompt(room_flags));
+ scr_flush();
while (1) {
ch = inkey();
if (cptr->c_cmdnum == this_lazy_cmd) {
for (a = 0; a < 5; ++a)
if (cptr->c_keys[a][0] != 0)
- printf("%s ", cmd_expand(
+ scr_printf("%s ", cmd_expand(
cptr->c_keys[a], 0));
- printf("\n");
+ scr_printf("\n");
return (this_lazy_cmd);
}
}
- printf("\n");
+ scr_printf("\n");
return (this_lazy_cmd);
}
/* Otherwise, process the command */
for (cptr = cmdlist; cptr != NULL; cptr = cptr->next) {
if (cmdmatch(cmdbuf, cptr, cmdpos + 1)) {
- printf("%s", cmd_expand(cptr->c_keys[cmdpos], 0));
+ scr_printf("%s", cmd_expand(cptr->c_keys[cmdpos], 0));
cmdspaces[cmdpos] = strlen(
cmd_expand(cptr->c_keys[cmdpos], 0));
if (cmdpos < 4)
if ((cptr->c_keys[cmdpos + 1]) != 0)
- putc(' ', stdout);
+ scr_putc(' ');
++cmdpos;
}
}
if (cmdmatch(cmdbuf, cptr, 5)) {
/* We've found our command. */
if (requires_string(cptr, cmdpos)) {
- getline(argbuf, 32);
+ ctdl_getline(argbuf, 64);
} else {
- printf("\n");
+ scr_printf("\n");
}
/* If this command is one that changes rooms,
|| (cptr->c_cmdnum == 20))
next_lazy_cmd = 13;
+ /* If this command is "read new"
+ * then the next lazy-command (space bar)
+ * should be "goto"
+ */
+ if (cptr->c_cmdnum == 13)
+ next_lazy_cmd = 5;
+
return (cptr->c_cmdnum);
}
for (cptr = cmdlist; cptr != NULL; cptr = cptr->next) {
if (cmdmatch(cmdbuf, cptr, cmdpos)) {
for (a = 0; a < 5; ++a) {
- pprintf("%s ", cmd_expand(cptr->c_keys[a], 1));
+ keyopt(cmd_expand(cptr->c_keys[a], 1));
+ pprintf(" ");
}
pprintf("\n");
}
}
+ sigcaught = 0;
pprintf("\n%s%c ", room_name, room_prompt(room_flags));
got = 0;
/*
* set tty modes. commands are:
*
- * 01- set to bbs mode
+ * 01- set to Citadel mode
* 2 - save current settings for later restoral
* 3 - restore saved settings
*/
#ifdef HAVE_TERMIOS_H
-void sttybbs(int cmd)
-{ /* SysV version of sttybbs() */
+void stty_ctdl(int cmd)
+{ /* SysV version of stty_ctdl() */
struct termios live;
static struct termios saved_settings;
static int last_cmd = 0;
live.c_oflag = OPOST | ONLCR;
live.c_lflag = ISIG | NOFLSH;
- live.c_cc[VINTR] = (-1);
- live.c_cc[VQUIT] = (-1);
+ live.c_cc[VINTR] = 0;
+ live.c_cc[VQUIT] = 0;
#ifdef hpux
live.c_cc[VMIN] = 0;
if (cmd == 3) {
tcsetattr(0, TCSADRAIN, &saved_settings);
}
+
}
#else
-void sttybbs(int cmd)
-{ /* BSD version of sttybbs() */
+void stty_ctdl(int cmd)
+{ /* BSD version of stty_ctdl() */
struct sgttyb live;
static struct sgttyb saved_settings;
+ static int last_cmd = 0;
+
+ if (cmd == SB_LAST)
+ cmd = last_cmd;
+ else
+ last_cmd = cmd;
if ((cmd == 0) || (cmd == 1)) {
gtty(0, &live);
/*
* display_help() - help file viewer
*/
-void display_help(char *name)
+void display_help(CtdlIPC *ipc, char *name)
{
- formout(name);
+ formout(ipc, name);
}
/*
- * fmout() - Citadel text formatter and paginator
+ * fmout() - Citadel text formatter and paginator
*/
int fmout(
int width, /* screen width to use */
- FILE *fp, /* file to read from, or NULL to read from server */
+ FILE *fpin, /* file to read from, or NULL to format given text */
+ char *text, /* text to be formatted (when fpin is NULL */
+ FILE *fpout, /* file to write to, or NULL to write to screen */
char pagin, /* nonzero if we should use the paginator */
int height, /* screen height to use */
int starting_lp,/* starting value for lines_printed, -1 for global */
- char subst) /* nonzero if we should use hypertext mode */
+ int subst) /* nonzero if we should use hypertext mode */
{
- int a, b, c, d, old;
- int real = (-1);
- char aaa[140];
- char buffer[512];
- int eof_flag = 0;
+ char *buffer = NULL; /* The current message */
+ char *word = NULL; /* What we are about to actually print */
+ char *e; /* Pointer to position in text */
+ char old = 0; /* The previous character */
+ int column = 0; /* Current column */
+ size_t i; /* Generic counter */
+
+ /* Space for a single word, which can be at most screenwidth */
+ word = (char *)calloc(1, width);
+ if (!word) {
+ err_printf("Can't alloc memory to print message: %s!\n",
+ strerror(errno));
+ logoff(NULL, 3);
+ }
- num_urls = 0; /* Start with a clean slate of embedded URL's */
+ /* Read the entire message body into memory */
+ if (fpin) {
+ buffer = load_message_from_file(fpin);
+ if (!buffer) {
+ err_printf("Can't print message: %s!\n",
+ strerror(errno));
+ logoff(NULL, 3);
+ }
+ } else {
+ buffer = text;
+ }
+ e = buffer;
- if (starting_lp >= 0) {
+ if (starting_lp >= 0)
lines_printed = starting_lp;
- }
- strcpy(aaa, "");
- old = 255;
- strcpy(buffer, "");
- c = 1; /* c is the current pos */
-
-FMTA: while ((eof_flag == 0) && (strlen(buffer) < 126)) {
- if (fp != NULL) { /* read from file */
- if (feof(fp))
- eof_flag = 1;
- if (eof_flag == 0) {
- a = getc(fp);
- buffer[strlen(buffer) + 1] = 0;
- buffer[strlen(buffer)] = a;
- }
- } else { /* read from server */
- d = strlen(buffer);
- serv_gets(&buffer[d]);
- while ((!isspace(buffer[d])) && (isspace(buffer[strlen(buffer) - 1])))
- buffer[strlen(buffer) - 1] = 0;
- if (!strcmp(&buffer[d], "000")) {
- buffer[d] = 0;
- eof_flag = 1;
- while (isspace(buffer[strlen(buffer) - 1]))
- buffer[strlen(buffer) - 1] = 0;
+
+ /* Run the message body */
+ while (*e) {
+ /* Catch characters that shouldn't be there at all */
+ if (*e == '\r') {
+ e++;
+ continue;
+ }
+ /* First, are we looking at a newline? */
+ if (*e == '\n') {
+ e++;
+ if (*e == ' ') { /* Paragraph */
+ if (fpout) {
+ fprintf(fpout, "\n");
+ } else {
+ scr_printf("\n");
+ ++lines_printed;
+ lines_printed = checkpagin(lines_printed, pagin, height);
+ }
+ column = 0;
+ } else if (old != ' ') {/* Don't print two spaces */
+ if (fpout) {
+ fprintf(fpout, " ");
+ } else {
+ scr_printf(" ");
+ }
+ column++;
}
- d = strlen(buffer);
- buffer[d] = 10;
- buffer[d + 1] = 0;
+ old = '\n';
+ continue;
}
- }
- if ( (!strncasecmp(buffer, "http://", 7))
- || (!strncasecmp(buffer, "ftp://", 6)) ) {
- safestrncpy(urls[num_urls], buffer, (SIZ-1));
- for (a=0; a<strlen(urls[num_urls]); ++a) {
- b = urls[num_urls][a];
- if ( (b==' ') || (b==')') || (b=='>') || (b==10)
- || (b==13) || (b==9) || (b=='\"') )
- urls[num_urls][a] = 0;
+ /* Are we looking at a nonprintable?
+ * (This section is now commented out because we could be displaying
+ * a character set like UTF-8 or ISO-8859-1.)
+ if ( (*e < 32) || (*e > 126) ) {
+ e++;
+ continue;
+ } */
+
+ /* Or are we looking at a space? */
+ if (*e == ' ') {
+ e++;
+ if (column >= width - 1) {
+ /* Are we in the rightmost column? */
+ if (fpout) {
+ fprintf(fpout, "\n");
+ } else {
+ scr_printf("\n");
+ ++lines_printed;
+ lines_printed = checkpagin(lines_printed, pagin, height);
+ }
+ column = 0;
+ } else if (!(column == 0 && old == ' ')) {
+ /* Eat only the first space on a line */
+ if (fpout) {
+ fprintf(fpout, " ");
+ } else {
+ scr_printf(" ");
+ }
+ column++;
+ }
+ /* ONLY eat the FIRST space on a line */
+ old = ' ';
+ continue;
+ }
+ old = *e;
+
+ /* Read a word, slightly messy */
+ i = 0;
+ while (e[i]) {
+ if (!isprint(e[i]) && !isspace(e[i]))
+ e[i] = ' ';
+ if (isspace(e[i]))
+ break;
+ i++;
}
- ++num_urls;
- }
-
- buffer[strlen(buffer) + 1] = 0;
- a = buffer[0];
- strcpy(buffer, &buffer[1]);
-
- old = real;
- real = a;
- if (a <= 0)
- goto FMTEND;
- if (((a == 13) || (a == 10)) && (old != 13) && (old != 10))
- a = 32;
- if (((old == 13) || (old == 10)) && (isspace(real))) {
- printf("\n");
- ++lines_printed;
- lines_printed = checkpagin(lines_printed, pagin, height);
- c = 1;
- }
- if (a > 126)
- goto FMTA;
-
- if (a > 32) {
- if (((strlen(aaa) + c) > (width - 5)) && (strlen(aaa) > (width - 5))) {
- printf("\n%s", aaa);
- c = strlen(aaa);
- aaa[0] = 0;
- ++lines_printed;
- lines_printed = checkpagin(lines_printed, pagin, height);
+ /* We should never see these, but... slightly messy */
+ if (e[i] == '\t' || e[i] == '\f' || e[i] == '\v')
+ e[i] = ' ';
+
+ /* Break up really long words */
+ /* TODO: auto-hyphenation someday? */
+ if (i >= width)
+ i = width - 1;
+ strncpy(word, e, i);
+ word[i] = 0;
+
+ /* Decide where to print the word */
+ if (column + i >= width) {
+ /* Wrap to the next line */
+ if (fpout) {
+ fprintf(fpout, "\n");
+ } else {
+ scr_printf("\n");
+ ++lines_printed;
+ lines_printed = checkpagin(lines_printed, pagin, height);
+ }
+ column = 0;
}
- b = strlen(aaa);
- aaa[b] = a;
- aaa[b + 1] = 0;
- }
- if (a == 32) {
- if ((strlen(aaa) + c) > (width - 5)) {
- c = 1;
- printf("\n");
- ++lines_printed;
- lines_printed = checkpagin(lines_printed, pagin, height);
+
+ /* Print the word */
+ if (fpout) {
+ fprintf(fpout, "%s", word);
+ } else {
+ scr_printf("%s", word);
}
- printf("%s ", aaa);
- ++c;
- c = c + strlen(aaa);
- strcpy(aaa, "");
- goto FMTA;
+ column += i;
+ e += i; /* Start over with the whitepsace! */
}
- if ((a == 13) || (a == 10)) {
- printf("%s\n", aaa);
- c = 1;
+
+ free(word);
+ if (fpin) /* We allocated this, remember? */
+ free(buffer);
+
+ /* Is this necessary? It makes the output kind of spacey. */
+ if (fpout) {
+ fprintf(fpout, "\n");
+ } else {
+ scr_printf("\n");
++lines_printed;
lines_printed = checkpagin(lines_printed, pagin, height);
- if (sigcaught) goto OOPS;
- strcpy(aaa, "");
- goto FMTA;
}
- goto FMTA;
- /* keypress caught; drain the server */
-OOPS: do {
- serv_gets(aaa);
- } while (strcmp(aaa, "000"));
-
-FMTEND: printf("\n");
- ++lines_printed;
- lines_printed = checkpagin(lines_printed, pagin, height);
- return (sigcaught);
+ return sigcaught;
}
*/
void color(int colornum)
{
- static int is_bold = 0;
- static int hold_color, current_color;
+ static int hold_color;
+ static int current_color;
if (colornum == COLOR_PUSH) {
hold_color = current_color;
current_color = colornum;
if (enable_color) {
+#if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
+ if (scr_color(colornum))
+ return;
+#endif
/* When switching to dim white, actually output an 'original
* pair' sequence -- this looks better on black-on-white
- * terminals.
+ * terminals. - Changed to ORIGINAL_PAIR as this actually
+ * wound up looking horrible on black-on-white terminals, not
+ * to mention transparent terminals.
*/
- if (colornum == DIM_WHITE)
- printf("\033[39;49m");
+ if (colornum == ORIGINAL_PAIR)
+ printf("\033[0;39;49m");
else
- printf("\033[3%d;40m", (colornum & 7));
-
- if ((colornum >= 8) && (is_bold == 0)) {
- printf("\033[1m");
- is_bold = 1;
- } else if ((colornum < 8) && (is_bold == 1)) {
- printf("\033[0m");
- is_bold = 0;
- }
- fflush(stdout);
+ printf("\033[%d;3%d;4%dm",
+ (colornum & 8) ? 1 : 0,
+ (colornum & 7),
+ rc_color_use_bg);
+
+ scr_flush();
}
}
void cls(int colornum)
{
if (enable_color) {
- printf("\033[4%dm\033[2J\033[H\033[0m", colornum);
- fflush(stdout);
+ printf("\033[4%dm\033[2J\033[H\033[0m",
+ colornum ? colornum : rc_color_use_bg);
+ scr_flush();
}
}
{
if (rc_ansi_color == 2) {
printf("\033[c");
- fflush(stdout);
+ scr_flush();
time(&AnsiDetect);
}
}
}
} while (FD_ISSET(0, &rfds));
- for (a = 0; a < strlen(abuf); ++a) {
+ for (a = 0; !IsEmptyStr(&abuf[a]); ++a) {
if ((abuf[a] == 27) && (abuf[a + 1] == '[')
&& (abuf[a + 2] == '?')) {
enable_color = 1;
int i;
color(DIM_WHITE);
- for (i=0; i<strlen(buf); ++i) {
+ for (i=0; !IsEmptyStr(&buf[i]); ++i) {
if (buf[i]=='<') {
- putc(buf[i], stdout);
+ pprintf("%c", buf[i]);
color(BRIGHT_MAGENTA);
} else {
- if (buf[i]=='>') {
+ if (buf[i]=='>'&& buf[i+1] != '>') {
color(DIM_WHITE);
}
- putc(buf[i], stdout);
+ pprintf("%c", buf[i]);
}
}
color(DIM_WHITE);
choices = num_tokens(menustring, '|');
if (menuprompt != NULL) do_prompt = 1;
- if (menuprompt != NULL) if (strlen(menuprompt)==0) do_prompt = 0;
+ if (menuprompt != NULL) if (IsEmptyStr(menuprompt)) do_prompt = 0;
while (1) {
if (display_prompt) {
if (do_prompt) {
- printf("%s ", menuprompt);
+ scr_printf("%s ", menuprompt);
}
else {
for (i=0; i<choices; ++i) {
- extract(buf, menustring, i);
+ extract_token(buf, menustring, i, '|', sizeof buf);
keyopt(buf);
- printf(" ");
+ scr_printf(" ");
}
}
- printf(" -> ");
+ scr_printf("-> ");
display_prompt = 0;
}
ch = lkey();
if ( (do_prompt) && (ch=='?') ) {
- printf("\rOne of... ");
- printf(" \n");
+ scr_printf("\rOne of... ");
+ scr_printf(" \n");
for (i=0; i<choices; ++i) {
- extract(buf, menustring, i);
- printf(" ");
+ extract_token(buf, menustring, i, '|', sizeof buf);
+ scr_printf(" ");
keyopt(buf);
- printf("\n");
+ scr_printf("\n");
}
- printf("\n");
+ scr_printf("\n");
display_prompt = 1;
}
for (i=0; i<choices; ++i) {
- extract(buf, menustring, i);
- for (c=1; c<strlen(buf); ++c) {
+ extract_token(buf, menustring, i, '|', sizeof buf);
+ for (c=1; !IsEmptyStr(&buf[c]); ++c) {
if ( (ch == tolower(buf[c]))
&& (buf[c-1]=='<')
&& (buf[c+1]=='>') ) {
- for (a=0; a<strlen(buf); ++a) {
+ for (a=0; !IsEmptyStr(&buf[a]); ++a) {
if ( (a!=(c-1)) && (a!=(c+1))) {
- putc(buf[a], stdout);
+ scr_putc(buf[a]);
}
}
- printf("\n\n");
+ scr_printf("\n");
return ch;
}
}