#include <sys/time.h>
#include <time.h>
#include <ctype.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <slang.h>
#include "slirc.h"
static int abort_char = 3; /* For MSDOS, use 34 as scan code */
static char Top2[100] = "";
struct _ProgressMeter {
struct _ProgressMeter *prev;
struct _ProgressMeter *next;
char *title;
int number;
int max;
int point;
};
static struct _ProgressMeter *PMfirst = NULL;
static struct _ProgressMeter *PMlast = NULL;
static int PMnum = 0; /* number of active PMs */
static char PM_dirty = 0;
static void DoExit(char *) __attribute__((noreturn));
void Fatal(char *) __attribute__((noreturn));
void SLirc_UpdateDisplay(void);
void SLirc_Log(char *);
char NullString[] = "";
static char *NullStringP = NullString;
int UseColours = 0;
SLang_Name_Type *VF_reset = NULL;
/*
* siz is the MAX # chars to write to dest,
* if siz>0 there will be a terminal '\0' written
* and return val points to that terminal zero
*/
char *strmcpy(char *dest, const char *src, int siz)
{
if (siz > 0) {
while (--siz)
if (!(*dest++ = *src++))
return --dest;
*dest = '\0';
}
return dest;
}
int IrcCmp(char *nika, char *nikb, int n)
{
register char cha;
register char chb;
char bang = 0;
while (n--) {
cha = *nika++;
chb = *nikb++;
if (cha != chb && !bang && LOWER_CASE(cha) != LOWER_CASE(chb))
return 1;
if (!cha) break;
if (cha == '!') bang = cha;
}
return 0;
}
/* void Topcat(char*cp) {strcat(Top2,cp);}*/
static void dflt_sig_handler(int signum)
{
char buf[130];
sprintf(buf, "Caught sig %d (%s)", signum, Top2);
SLang_doerror(buf);
if (VF_reset) SLexecute_function(VF_reset);
exit(1);
}
#define MAXPMS 50
int Rpms_ct;
static int R_trailing; /* nonzero is ix of trailing field */
char *Rpms[MAXPMS];
static void Create_Rpms_Array(void)
{
int i, r;
for (i = MAXPMS; i > 0;)
Rpms[--i] = "";
r = SLang_add_intrinsic_array(
"Rpms", /* slang name */
SLANG_STRING_TYPE,
1, /* Readonly array */
Rpms, /* location of the array */
1, /* number of dimensions */
MAXPMS); /* number of elements in X direction */
if (r)
Fatal("Failed to add Rpms array");
}
/*
* int ParseReturn(char *cp)
* cp points to a null-terminated line of data,
* which MAY have a \n or \r\n at the end.
* it is copied to an internal buffer, less it's
* \n or \r\n, then parsed in place into null-terminated
* parameter strings.
*
* Rpms[n] will be a pointer to the nth string.
* Rpms[0] will be the PREFIX field (if any), otherwise a NullString.
* Rpms_ct will be the total number of params, counting
* the possibly NullString prefix.
* Rpms_ct is also the return-value of the function,
* 0 indicates some sort of error.
* R_trailing will be set to the INDEX of the 'trailing'
* parameter (if any), otherwise to 0. So that if it
* is nonzero, it will obviously equal (Rpms_ct - 1).
*/
static int ParseReturn(char *cp0)
{
static char RBuf[1025];
/*
* Static because I hate autoing tonnes of stuff all the time...
*/
int Num;
char *cp,*pm;
char stop, ch;
cp = strmcpy(RBuf, cp0, sizeof(RBuf));
/* now cp points to the terminating null in RBuf */
while(1) {
if (cp > RBuf && *(cp-1) == '\n') { /* back up past '\n' if is one. */
cp--;
if (cp > RBuf && *(cp-1) == '\r') cp--;
*cp = '\0';
}
if (NULL == (cp = index(RBuf, '\n'))) break;
SLirc_Log("Buffer has multiple lines. Weird.");
SLirc_UpdateDisplay();
}
cp = RBuf;
/* strmcpy(Top2, cp, sizeof(Top2) - 15); SetTop(cp); */
for (Num = 10; Num > 0;) Rpms[--Num] = "";
/* now Num=0 */
R_trailing = 0;
if (*cp++ != ':') { /* no prefix */
cp--;
Num++;
}
stop = ' '; /* field delimiter */
while (*cp == stop)
cp++; /*skip space */
while (1) {
pm = cp;
while ((ch = *cp) && ch != stop)
cp++; /*skip to space or \0 */
*cp++ = '\0';
if (Num < MAXPMS - 1)
Rpms[Num++] = pm;
if (!ch)
break;
while ((ch = *cp) == ' ')
cp++; /*skip space */
if (ch != ':')
continue;
stop = '\0';
cp++;
R_trailing = Num;
}
Rpms_ct = Num;
return Num;
}
/* because we don't like the "\r\n" used in slang itself: */
static void Local_vmessage(char *fmt, va_list ap)
{
vfprintf (stdout, fmt, ap);
fputs ("\n", stdout);
}
char Target[81] = "NOTARGET";
static char Top[75];
static char Status[256];
static char StatMsg[50] = "NOSTATUS";
#define EntryBuffLen 510
struct _EntryBox {
int Offset; /* s[Offset] is 1st char in window */
int Insert; /* s[Insert] is the cursor location */
int mode; /* was CommandMode */
char dirty; /* nonzero means need redraw */
char s[EntryBuffLen];
char Prompts[2][12]; /* normal and over prompts */
};
static struct _EntryBox CommandBox = {
0, 0, 0, 1,
"", {"> ", "$ "}
};
static char *CommandTextP = CommandBox.s;
static char GotWinch = 0;
static char Top_dirty = 1;
static char Status_dirty = 1;
static char *TargetP = Target;
char ServerName[128] = "";
static char ClientName[128] = "localhost";
char NickName[10] = ""; /* for various display funcs */
static char UserName[10] = "";
static char *ServerNameP = ServerName;
static char *ClientNameP = ClientName;
static char *NickNameP = NickName;
static char *UserNameP = UserName;
static const char *ProgNameP = "SLirc";
static const char *ProgVersionP = VERSION;
static const char *CFG_DIRP = CFG_DIR;
/* static unsigned long LastRecvTime = 0; */
static int ShowInfo = 1;
static int SrvTime = 0;
static void DrawStatus(int start)
{
char secs[8];
snprintf(Status, sizeof(Status), "%s -> %s Server[%s] %s",
NickName, Target, ServerName, StatMsg);
SLsmg_gotorc(start, 0);
SLsmg_set_color(UseColours? ColStatusSay + CommandBox.mode : 1); /* HACK! */
SLsmg_write_string(Status);
SLsmg_erase_eol();
sprintf(secs,"%3d",SrvTime);
SLsmg_gotorc(start, SLtt_Screen_Cols - 10);
SLsmg_write_string(secs);
if (!ShowInfo) {
SLsmg_gotorc(start, SLtt_Screen_Cols - 6);
SLsmg_write_string("NOINFO");
}
SLsmg_set_color(UseColours? ColDefault : 0);
Status_dirty = 0;
}
static void DrawTop(int start)
{
SLsmg_gotorc(start, 0);
SLsmg_set_color((UseColours) ? ColTopNorm : 1);
SLsmg_write_string(Top);
SLsmg_erase_eol();
SLsmg_set_color((UseColours) ? ColDefault : 0);
Top_dirty = 0;
}
static void SetTop(char *st)
{
if (strcmp(Top,st)) {
strmcpy(Top, st, sizeof(Top));
Top_dirty = 1;
}
}
static void DrawEntryBox(struct _EntryBox *b, int y0)
{
char *prompt;
int promptlen, over,roff;
int x0 = 0;
int x1 = SLtt_Screen_Cols;
if (b->Offset > b->Insert) b->Offset = b->Insert;
while (1) {
int rshift;
over = (b->Offset > 0)? 1:0;
prompt = b->Prompts[over];
promptlen = strlen(prompt);
roff = x0 + promptlen + b->Insert - b->Offset;
rshift = roff - (x1 - 1);
if (rshift <= 0) break;
b->Offset += rshift;
}
SLsmg_gotorc(y0, x0);
SLsmg_set_color((UseColours) ? ColBufferPromptSayNorm + 2*b->mode + over : 0);
SLsmg_write_string(prompt);
SLsmg_set_color((UseColours) ? ColBufferTextSay + b->mode : 0);
SLsmg_write_nstring(b->s + b->Offset, x1-x0-promptlen);
/* SLsmg_erase_eol(); */
SLsmg_gotorc(y0, roff);
SLsmg_set_color((UseColours) ? ColDefault : 0);
b->dirty = 0;
}
static void SLirc_SetCommandBox(char *st)
{
struct _EntryBox *b;
b = &CommandBox;
if (b->s == strmcpy(b->s, st, EntryBuffLen)) { /* was "" */
b->Insert = 0;
b->Offset = 0;
b->mode = 0;
}
b->dirty = 1;
}
/*
* SLirc API stuff here.
*/
static void SLirc_InitVarsDefault(void)
{
char *p, *q;
if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")))
p = "ircuser";
strmcpy(UserName, p, sizeof(UserName));
if (!(q = getenv("IRCNICK"))) q = p;
strmcpy(NickName, q, sizeof(NickName));
/* now for scripts search-path */
if((q = getenv("HOME")))
snprintf(SLirc_Load_Path, 196, "%s/.slirc/scripts",q);
else
snprintf(SLirc_Load_Path, 196, "/home/%s/.slirc/scripts",p);
if (2 != SLpath_file_exists(SLirc_Load_Path))
SLirc_Load_Path[0] = '\0';
else
strcat(SLirc_Load_Path, ":");
strcat(SLirc_Load_Path,SCRIPTPATH); /* SCRIPTPATH defined in Makefile */
}
/*
* SetStatus(char *) -> set_status(string)
* Sets StatMsg part of status line.
*/
static void SetStatus(char *st)
{
if (strcmp(StatMsg,st)) {
strmcpy(StatMsg,st,sizeof(StatMsg));
Status_dirty = 1;
}
}
static void SLirc_SetNick(char *st)
{
if (strcmp(NickName,st)) {
strmcpy(NickName, st, sizeof(NickName));
Status_dirty = 1;
DirtyWindow();
}
}
static void SLirc_SetServerName(char *st)
{
if (strcmp(ServerName,st)) {
strmcpy(ServerName, st, sizeof(ServerName));
Status_dirty = 1;
}
}
static void SLirc_SetTarget(char *st)
{
if (IrcCmp(Target,st,-1)) {
/* really changed */
strmcpy(Target, st, sizeof(Target));
Status_dirty = 1;
DirtyWindow();
}
}
static void SLirc_SetSrvTime(int *y)
{
if (SrvTime != *y) {
SrvTime = *y;
Status_dirty = 1;
DirtyWindow();
}
}
static void SLirc_SetShowInfo(int *y)
{
int v = (*y != 0);
if (ShowInfo != v) {
/* really changed */
ShowInfo = v;
Status_dirty = 1;
DirtyWindow();
}
}
static void SetLoadPath(char *st)
{
strmcpy(SLirc_Load_Path, st, 196);
}
static void SLirc_Colour(int *which, char *fg, char *bg)
{
/*
* which comes from a bunch of iconstants setup here.
* Bit of a pain, but easier than having weird numbers in the scripts.
*/
SLtt_set_color(*which, NULL, fg, bg);
}
void SLirc_Log(char *text)
{
SLirc_Multn(text, NULL, NULL, IRC_TYPE_LOG);
}
static void SLirc_Info(char *text, char *to)
{
SLirc_Multn(text, NULL, to, IRC_TYPE_INFO);
}
static void SLirc_Action(char *text, char *from, char *to)
{
SLirc_Multn(text, from, to, IRC_TYPE_ACTION);
}
static void SLirc_Say(char *text, char *from, char *to)
{
SLirc_Multn(text, from, to, IRC_TYPE_SAY);
}
void SLirc_Log_Error(char *st)
{
static FILE *fp = NULL;
if (!fp)
fp = fopen("error_log", "w");
SLirc_Log(st);
if (fp)
fprintf(fp, "%s\n", st);
}
static void InitMainScreen(void)
{
SLsmg_cls();
Init_Windows();
strcpy(Top, " *** SLirc *** ");
strcpy(Status, "*|*@*->*: Init");
/* CommandBox.s[0] = '\0'; */
DrawTop(1);
DrawStatus(SLtt_Screen_Rows - 2);
DrawEntryBox(&CommandBox, SLtt_Screen_Rows - 1);
SLsmg_refresh();
}
/* shouldn't do much inside a signal-handler */
static void whoops_the_screen_size_has_changed(int sig)
{
GotWinch = 1;
SLsignal(SIGWINCH, whoops_the_screen_size_has_changed);
}
static int PU_dirty = 0;
static char *PU_title = NULL;
static char *PU_func;/* function to be executed with keypresses */
static int PU_maxln;
static int PU_i0; /* 1st in window (advisory) */
static int PU_ix; /* currently selected */
static int PU_ct; /* number of items */
static char* PU_items[250];
static void HadWinch(void)
{
char buf[80];
SLang_init_tty(abort_char, 0, 0); /* cslang.txt says do this after WINCH */
SLtt_get_screen_size(); /* this IS necessary */
SLsmg_init_smg(); /* does SLsmg_reset_smg() inside. */
/* Note: SLsmg_init_smg() unblocks signals */
sprintf(buf, "SIGWINCH: New size=%dx%d", SLtt_Screen_Rows, SLtt_Screen_Cols);
SLirc_Log(buf);
SLsmg_touch_lines(0, SLtt_Screen_Rows); /* probably redundant */
LRU_dirty = 1;
Top_dirty = 1;
DirtyWindow();
PM_dirty = 1;
PU_dirty = 1;
Status_dirty = 1;
CommandBox.dirty = 1;
GotWinch = 0;
}
static void DrawPopUp(void)
{
int c0,r0; /* column,row of upper-left corner of window box */
int cs,rs; /* # cols,rows available for items in window */
int i,r,c;
int col_item;
int col_isel;
char *p0;
char format[20];
col_item = UseColours? ColPopItem:0;
col_isel = UseColours? ColPopISel:1;
/* these calculations try to center popup INSIDE the LW-window area: */
rs = SLtt_Screen_Rows-6-PMnum; if (rs > PU_ct) rs = PU_ct;
r0 = (SLtt_Screen_Rows + PMnum - rs - 2)/2;
cs = SLtt_Screen_Cols-4; if (cs > PU_maxln) cs = PU_maxln;
c0 = (SLtt_Screen_Cols - cs - 2)/2;
p0 = SLmalloc(cs+1); /* a buffer for truncation if necessary */
/* make minimal adjustment of PU_i0, if necessary, so that */
/* selected item PU_ix is IN window: */
if (PU_ix < PU_i0)
PU_i0 = PU_ix;
else if (PU_ix - rs + 1 > PU_i0)
PU_i0 = PU_ix - rs + 1;
SLsmg_set_color(UseColours? ColPopBord:1);
SLsmg_draw_box(r0,c0,rs+2,cs+2);
if (!p0) return;
strmcpy(p0,PU_title,cs+1);
SLsmg_gotorc(r0, c0 + 1 + (cs-strlen(p0))/2);
SLsmg_write_string(p0);
sprintf(format,"%%-%ds",cs);
r = r0+1;
c = c0+1;
for (i = PU_i0; i<PU_i0+rs; i++, r++) {
SLsmg_gotorc(r, c);
SLsmg_set_color((i == PU_ix)? col_isel : col_item);
strmcpy(p0,PU_items[i],cs+1);
SLsmg_printf(format,p0);
/* SLsmg_write_char('>'); */
}
PU_dirty = 0;
SLfree(p0);
}
static void SLirc_create_popup(char *title, char *items, char *handler)
{
int ct, maxln = strlen(title);
char *p,*q;
if (PU_title) return; /* for now */
PU_title = SLmake_string(title);
PU_func = SLmake_string(handler);
for (ct = 0, p = items; *p && ct < 250; p = q) {
int l;
q = index(p,'\n');
if (!q) q = p + strlen(p);
l = q-p;
PU_items[ct++] = SLmake_nstring(p,l);
if (maxln < l) maxln = l;
if (*q) q++;
}
PU_maxln = maxln;
PU_ct = ct; /* the hard-coded limit of 250 will be eliminated some day :) */
PU_i0 = 0;
PU_ix = 0;
PU_dirty = 1;
return;
}
static void SLirc_destroy_popup(void)
{
int i;
if (!PU_title) return; /* for now */
SLfree(PU_title);
PU_title = NULL;
SLfree(PU_func);
for (i = 0; i < PU_ct; i++) SLfree(PU_items[i]);
PU_dirty = 0;
DirtyWindow();
return;
}
static void DrawProgress(int start)
{
struct _ProgressMeter *pm;
int rows = start;
for (pm = PMfirst; pm; pm = pm->next) {
int width;
int point;
int percent;
int i;
char buf[8];
SLsmg_gotorc(rows, 0);
width = SLtt_Screen_Cols - strlen(pm->title) - 10;
point = (pm->point * width) / pm->max;
percent = (pm->point * 100) / pm->max;
sprintf(buf, "%d", percent);
SLsmg_set_color(UseColours? ColTopNorm : 1);
SLsmg_write_string(pm->title);
SLsmg_write_string(" : ");
SLsmg_write_string(buf);
SLsmg_write_string("% : |");
for (i = 0; i < width; i++) {
if (i < point)
SLsmg_write_char('-');
else if (i == point)
SLsmg_write_char('>');
else
SLsmg_write_char(' ');
}
SLsmg_write_char('|');
SLsmg_erase_eol();
rows++;
}
PM_dirty = 0;
}
static int SLirc_create_progress_meter(char *title, int *scale)
{
struct _ProgressMeter *pm = (struct _ProgressMeter *) SLmalloc(sizeof(struct _ProgressMeter));
pm->prev = PMlast;
pm->next = NULL;
pm->title = SLmake_string(title);
pm->max = *scale;
pm->point = 0;
/*
* List insertion.
*/
if (PMfirst && PMlast)
pm->prev->next = pm;
else
PMfirst = pm;
PMlast = pm;
PMnum++;
/*
* Find a tag.
*/
if (PMfirst == pm)
pm->number = 1;
else
pm->number = PMlast->number + 1;
PM_dirty = 1;
DirtyWindow();
return (pm->number);
}
static void SLirc_destroy_progress_meter(int *which)
{
struct _ProgressMeter *pm;
for (pm = PMfirst; pm; pm = pm->next) {
if (pm->number == *which)
break;
}
if (pm) {
if (pm->next)
pm->next->prev = pm->prev;
else
PMlast = pm->prev;
if (pm->prev)
pm->prev->next = pm->next;
else
PMfirst = pm->next;
SLfree(pm->title);
SLfree((char*)pm);
PMnum--;
PM_dirty = 1;
DirtyWindow();
}
}
static void SLirc_set_progress_meter(int *which, int *point)
{
struct _ProgressMeter *pm;
for (pm = PMfirst; pm; pm = pm->next)
if (pm->number == *which)
break;
if (pm) {
int percent0,percent1,pt = *point;
if (pt < 0) pt = 0;
else if (pt > pm->max) pt = pm->max;
percent0 = (pm->point * 100) / pm->max;
percent1 = (pt * 100) / pm->max;
pm->point = pt;
if (percent0 != percent1) PM_dirty = 1; /* redisplay only if changed */
}
}
void SLirc_UpdateDisplay()
{
/* All well behaved applications should block signals that may affect
* the display while performing screen update.
*/
while (1) {
SLsig_block_signals();
if (!GotWinch) break;
HadWinch();
/* HadWinch() re-inits SLmsg,etc and marks everything dirty */
/* also, the SLsmg_init unblocks sigs, so we need to loop... */
}
if (LRU_dirty) DrawLRU(0);
if (Top_dirty) DrawTop(1);
if (PM_dirty) DrawProgress(2);
if (DrawAllWindows(2+PMnum, SLtt_Screen_Rows - (4+PMnum)))
if (PU_title) PU_dirty=1;
if (PU_dirty) DrawPopUp();
if (Status_dirty) DrawStatus(SLtt_Screen_Rows - 2);
DrawEntryBox(&CommandBox, SLtt_Screen_Rows - 1); /* positions cursor, too */
SLsmg_refresh();
SLsig_unblock_signals();
}
static void DoExit(char *st)
{
SLsmg_reset_smg();
SLang_reset_tty();
if (VF_reset) SLexecute_function(VF_reset);
SLang_doerror(st);
puts(st);
exit(1);
}
void Fatal(char *st)
{
SLsmg_reset_smg();
SLang_reset_tty();
if (VF_reset) SLexecute_function(VF_reset);
puts(st);
exit(2);
}
static void ClearSomeErrors(void)
{
if (SLang_Error && SLang_Error != USER_BREAK) {
SLang_Error = 0;
SLsmg_touch_lines(0, SLtt_Screen_Rows);
SLirc_UpdateDisplay();
SLang_input_pending(20);
}
}
static int SLirc_define_keysym(char *st, int *ch)
{
return SLkp_define_keysym(st, *ch);
}
static unsigned int KeySymNext = 0x1000;
typedef struct _KbdAssocArray {
struct _KbdAssocArray *prev;
struct _KbdAssocArray *next;
unsigned int ksym;
char *fn;
unsigned int pass;
} KbdAssocArray;
KbdAssocArray *Ksyms = NULL;
KbdAssocArray *LastKsym = NULL;
static int SLirc_KdbAssoc(char *st, char *fn, int *pass)
{
int res;
KbdAssocArray *kbd = (KbdAssocArray *) SLmalloc(sizeof(KbdAssocArray));
kbd->ksym = KeySymNext;
kbd->fn = SLmake_string(fn);
kbd->pass = *pass;
kbd->prev = LastKsym;
kbd->next = NULL;
if (LastKsym)
LastKsym->next = kbd;
else
Ksyms = kbd;
res = SLkp_define_keysym(st, KeySymNext);
KeySymNext++;
LastKsym = kbd;
return res;
}
static int SLirc_KdbAssocKeysym(int *ksym, char *fn, int *pass)
{
int res = 1;
KbdAssocArray *kbd = (KbdAssocArray *) SLmalloc(sizeof(KbdAssocArray));
kbd->ksym = *ksym;
kbd->fn = SLmake_string(fn);
kbd->pass = *pass;
kbd->prev = LastKsym;
kbd->next = NULL;
if (LastKsym)
LastKsym->next = kbd;
else
Ksyms = kbd;
LastKsym = kbd;
return res;
}
static int SLirc_RunKeysym(unsigned int *ksym)
{
int res = 0;
int myksym = *ksym;
KbdAssocArray *kbd;
if (PU_title) {
if (*ksym == SL_KEY_UP) {
if (PU_ix > 0) PU_ix--;
PU_dirty = 1;
}else if (*ksym == SL_KEY_DOWN) {
if (PU_ix < PU_ct - 1) PU_ix++;
PU_dirty = 1;
}else if (!*PU_func) {
SLirc_destroy_popup();
goto passthru;
}else{ /* execute handler */
SLang_push_integer(*ksym);
SLang_push_integer(PU_ix);
SLang_push_string(PU_items[PU_ix]);
SLang_execute_function(PU_func);/* change this to use SLexecute? */
ClearSomeErrors();
}
return -1;
}
passthru:
for (kbd = Ksyms; kbd; kbd = kbd->next) {
if (kbd->ksym == myksym) {
if (SLang_is_defined(kbd->fn)) {
if (kbd->pass)
SLang_push_integer(myksym);
SLang_execute_function(kbd->fn); /* change this to use SLexecute? */
ClearSomeErrors();
res = 1;
} else {
SLirc_Log("Missing function?");
}
}
}
return (res);
}
#define I SLANG_INT_TYPE
#define S SLANG_STRING_TYPE
#define V SLANG_VOID_TYPE
static SLang_Intrin_Fun_Type SLirc_Fun_Table[] =
{
MAKE_INTRINSIC_S("define_for_ifdef", SLdefine_for_ifdef, I),
MAKE_INTRINSIC_S("irc_set_nickname", SLirc_SetNick, V),
MAKE_INTRINSIC_S("irc_set_servername", SLirc_SetServerName, V),
MAKE_INTRINSIC_S("irc_set_target", SLirc_SetTarget, V),
MAKE_INTRINSIC_I("irc_set_srvtime", SLirc_SetSrvTime, V),
MAKE_INTRINSIC_S("irc_parse_params", ParseReturn, I),
MAKE_INTRINSIC_S("irc_set_path", SetLoadPath, V),
MAKE_INTRINSIC_I("irc_set_showinfo", SLirc_SetShowInfo, V),
MAKE_INTRINSIC_S("irc_set_buffer", SLirc_SetCommandBox, V),
MAKE_INTRINSIC_S("irc_set_top", SetTop, V),
MAKE_INTRINSIC_S("irc_set_status", SetStatus, V),
MAKE_INTRINSIC_0("irc_update_display", SLirc_UpdateDisplay, V),
MAKE_INTRINSIC_S("irc_log", SLirc_Log, V),
MAKE_INTRINSIC_SS("irc_info", SLirc_Info, V),
MAKE_INTRINSIC_SSS("irc_say", SLirc_Say, V),
MAKE_INTRINSIC_SSS("irc_action", SLirc_Action, V),
MAKE_INTRINSIC_S("irc_exit", DoExit, V),
MAKE_INTRINSIC_0("irc_beep", SLtt_beep, V),
MAKE_INTRINSIC_0("irc_get_input", SLkp_getkey, I),
MAKE_INTRINSIC_SI("define_keysym", SLirc_define_keysym, I),
MAKE_INTRINSIC_SSI("irc_set_key", SLirc_KdbAssoc, I),
MAKE_INTRINSIC_ISI("irc_set_keysym", SLirc_KdbAssocKeysym, I),
MAKE_INTRINSIC_I("irc_exec_key", SLirc_RunKeysym, I),
MAKE_INTRINSIC_ISS("irc_set_colour", SLirc_Colour, V),
MAKE_INTRINSIC_SI("irc_create_pm", SLirc_create_progress_meter, I),
MAKE_INTRINSIC_II("irc_set_pm", SLirc_set_progress_meter, V),
MAKE_INTRINSIC_I("irc_destroy_pm", SLirc_destroy_progress_meter, V),
MAKE_INTRINSIC_SSS("irc_create_popup", SLirc_create_popup, V),
MAKE_INTRINSIC_0("irc_destroy_popup", SLirc_destroy_popup, V),
SLANG_END_TABLE
};
static SLang_Intrin_Var_Type SLirc_Var_Table[] =
{
MAKE_VARIABLE("NullString", &NullStringP, S, 1),
MAKE_VARIABLE("ProgName", &ProgNameP, S, 1),
MAKE_VARIABLE("ProgVersion", &ProgVersionP, S, 1),
MAKE_VARIABLE("slirc_home", &CFG_DIRP, S, 1),
MAKE_VARIABLE("irc_nickname", &NickNameP, S, 1),
MAKE_VARIABLE("irc_username", &UserNameP, S, 1),
MAKE_VARIABLE("irc_clientname", &ClientNameP, S, 1),
MAKE_VARIABLE("irc_servername", &ServerNameP, S, 1),
MAKE_VARIABLE("irc_target", &TargetP, S, 1),
MAKE_VARIABLE("irc_showinfo", &ShowInfo, I, 1),
MAKE_VARIABLE("R_trailing", &R_trailing, I, 1),
MAKE_VARIABLE("Rpms_ct", &Rpms_ct, I, 1),
/* next few are re edit command-buffer */
MAKE_VARIABLE("irc_buffer", &CommandTextP, S, 1),
MAKE_VARIABLE("irc_edit_insert_pos", &CommandBox.Insert, I, 0),
MAKE_VARIABLE("irc_command_mode", &CommandBox.mode, I, 0),
# if 0
MAKE_VARIABLE("irc_recv_time", &LastRecvTime, SLANG_ULONG_TYPE, 0),
# endif
MAKE_VARIABLE("irc_use_colours", &UseColours, I, 0),
SLANG_END_TABLE
};
#undef I
#undef S
#undef V
static SLang_IConstant_Type SLirc_Constants [] =
{
MAKE_ICONSTANT("irc_col_default", ColDefault),
MAKE_ICONSTANT("irc_col_top_norm", ColTopNorm),
MAKE_ICONSTANT("irc_col_auto_resp", ColAutoResp),
MAKE_ICONSTANT("irc_col_top_hi", ColTopHi),
MAKE_ICONSTANT("irc_col_status_say", ColStatusSay),
MAKE_ICONSTANT("irc_col_status_command", ColStatusCommand),
MAKE_ICONSTANT("irc_col_log_tag", ColLogTag),
MAKE_ICONSTANT("irc_col_log_text", ColLogText),
MAKE_ICONSTANT("irc_col_info_text", ColInfoText),
MAKE_ICONSTANT("irc_col_say_norm_send", ColSayNormSend),
MAKE_ICONSTANT("irc_col_say_tgto_send", ColSayTgtoSend),
MAKE_ICONSTANT("irc_col_say_norm_dec", ColSayNormDec),
MAKE_ICONSTANT("irc_col_say_norm_text", ColSayNormText),
MAKE_ICONSTANT("irc_col_say_hi_send", ColSayHiSend),
MAKE_ICONSTANT("irc_col_say_hi_dec", ColSayHiDec),
MAKE_ICONSTANT("irc_col_say_hi_text", ColSayHiText),
MAKE_ICONSTANT("irc_col_say_me_send", ColSayMeSend),
MAKE_ICONSTANT("irc_col_say_me_dec", ColSayMeDec),
MAKE_ICONSTANT("irc_col_say_me_text", ColSayMeText),
MAKE_ICONSTANT("irc_col_msg_norm_send", ColMsgNormSend),
MAKE_ICONSTANT("irc_col_msg_norm_dec", ColMsgNormDec),
MAKE_ICONSTANT("irc_col_msg_norm_text", ColMsgNormText),
MAKE_ICONSTANT("irc_col_msg_me_send", ColMsgMeSend),
MAKE_ICONSTANT("irc_col_msg_me_dec", ColMsgMeDec),
MAKE_ICONSTANT("irc_col_msg_me_text", ColMsgMeText),
MAKE_ICONSTANT("irc_col_buffer_prompt_say_norm", ColBufferPromptSayNorm),
MAKE_ICONSTANT("irc_col_buffer_prompt_say_over", ColBufferPromptSayOver),
MAKE_ICONSTANT("irc_col_buffer_prompt_cmd_norm", ColBufferPromptCommandNorm),
MAKE_ICONSTANT("irc_col_buffer_prompt_cmd_over", ColBufferPromptCommandOver),
MAKE_ICONSTANT("irc_col_buffer_text_say", ColBufferTextSay),
MAKE_ICONSTANT("irc_col_buffer_text_command", ColBufferTextCommand),
MAKE_ICONSTANT("irc_col_buffer_text_bold", ColBufferTextBold),
MAKE_ICONSTANT("irc_col_popup_border", ColPopBord),
MAKE_ICONSTANT("irc_col_popup_item", ColPopItem),
MAKE_ICONSTANT("irc_col_popup_select", ColPopISel),
SLANG_END_TABLE
};
static int init_SLirc(void)
{
if(SLdefine_for_ifdef("SLIRC")) return 0;
return (!SLadd_intrin_fun_table(SLirc_Fun_Table, "_SLirc") &&
!SLadd_intrin_var_table(SLirc_Var_Table, NULL) &&
!SLadd_iconstant_table (SLirc_Constants, NULL));
}
static int do_act_secs = 3;
int main(int argc, char **argv)
{
unsigned int expiry;
SLang_Name_Type *VF_do_actions;
SLang_Name_Type *check_timed = NULL;
SLirc_InitVarsDefault();
SLtt_get_terminfo(); /* Get the terminal info. */
SLtt_Use_Ansi_Colors = 1;
if (-1 == SLkp_init()) {
SLang_doerror("SLkp_init failed.");
exit(1);
}
/*
* Note: cref.txt says param 3 (opost) of SLang_init_tty()
* should be 0 when SLsmg is used.
* (actually, opost's ignored in slang-1.0.3 )
*/
if (-1 == SLang_init_tty(abort_char, 0, 0)) {
SLang_doerror("Unable to initialize the terminal.");
exit(1);
}
SLsmg_init_smg(); /* this does get_screen_size inside. */
SLang_set_abort_signal(NULL);
InitMainScreen();
SLang_VMessage_Hook = Local_vmessage;
SLang_Load_File_Hook = Local_SLang_load_file;
SLang_Error_Hook = SLirc_Log_Error;
SLang_Dump_Routine = SLirc_Log_Error;
/* VF_do_actions_Hook = SLirc_UpdateDisplay; */
SLang_Traceback = 1;
SLirc_Log("SLirc: Copyright 1997,1998 Dave Cridland, all rights reserved.");
SLirc_Log("SLirc: Copyright 1997,1998 Stan Brooks, all rights reserved.");
SLirc_Log("SLirc: Redistributable under GPL or PAL, see COPYRIGHT for info.");
SetStatus("Initializing SLang...");
if (SLang_init_slang() || SLang_init_slmath() ||
SLang_init_posix_dir() || SLang_init_import())
DoExit("Ooops. SLang init failed.");
SetStatus("Initializing SLang SLirc API...");
if (!init_SLirc())
DoExit("Ooops. SLirc init failed.");
if (!init_LRU())
DoExit("Ooops. LRU init failed.");
Create_Rpms_Array();
/* try to trap SIGSEGV's */
SLsignal(SIGSEGV, dflt_sig_handler);
/*
* ignore the SIGPIPE's caused on TCP write to closed connection
* we just handle the EPIPE after write()
*/
SLsignal(SIGPIPE, SIG_IGN);
SLsignal(SIGWINCH, whoops_the_screen_size_has_changed);
SetStatus("Loading SLirc init script...");
SLirc_UpdateDisplay();
SLang_load_file(argv[1] ? argv[1] : "init.sl");
if (SLang_Error) {
SLang_doerror("Oh, shit. Who fucked up that file, then?");
SLang_Error = 0;
}
SLtt_Use_Ansi_Colors = UseColours;
SLirc_UpdateDisplay();
VF_do_actions = SLang_get_function("do_actions");
if (!VF_do_actions) Fatal("do_actions is undefined");
VF_reset = SLang_get_function("vf_reset");
if (!VF_reset) Fatal("vf_reset is undefined");
check_timed = SLang_get_function("check_timed");
if (!check_timed) Fatal("check_timed is undefined");
expiry = time(NULL)+5;
while (SLang_Error != USER_BREAK) {
int r,stkdep;
unsigned int tim;
SLang_start_arg_list();
SLang_push_integer(do_act_secs);
SLang_end_arg_list();
r = SLexecute_function(VF_do_actions);
if (r==-1) Fatal("SLexecute_function(do_actions)?");
if (-1==SLang_pop_integer(&r)) Fatal("do_actions(): no integer");
# if 0
r = VF_do_actions(&do_act_secs); /* most everything executes from here */
/* r is how many SLang functions executed */
# endif
if (r>0 || GotWinch) SLirc_UpdateDisplay();
ClearSomeErrors();
tim = time(NULL);
if (tim<expiry) continue;
expiry += 5;
stkdep = _SLstack_depth();
r = SLexecute_function(check_timed);
if (r==-1) Fatal("SLexecute_function(check_timed)?");
# if 0
r = SLang_execute_function("check_timed");
if (!r) Fatal("check_timed is undefined");
# endif
SLirc_UpdateDisplay();
stkdep = _SLstack_depth() - stkdep; /* % items left on stack. */
if (stkdep && SLang_Error != USER_BREAK) {
SLang_verror(SL_APPLICATION_ERROR,
"Eeek... check_timed() left %d units on stack",stkdep);
if (stkdep>0) SLdo_pop_n(stkdep);
SLirc_UpdateDisplay();
}
ClearSomeErrors();
}
SLsmg_reset_smg();
SLang_reset_tty();
if (VF_reset) SLexecute_function(VF_reset);
exit(0);
}
syntax highlighted by Code2HTML, v. 0.9.1