#include #include #include #include #include #include #include #include #include #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_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 (tim0) SLdo_pop_n(stkdep); SLirc_UpdateDisplay(); } ClearSomeErrors(); } SLsmg_reset_smg(); SLang_reset_tty(); if (VF_reset) SLexecute_function(VF_reset); exit(0); }