/* -*- mode: C; mode: fold -*- */ #include "config.h" #include "slrnfeat.h" #include /* rest of file inside this #if statement */ #if SLRN_HAS_SLANG /*{{{ Include files */ #if HAVE_STDLIB_H # include #endif #include #include #include "jdmacros.h" #include "slrn.h" #include "group.h" #include "art.h" #include "misc.h" #include "startup.h" #include "server.h" #include "menu.h" #include "interp.h" #include "util.h" /*}}}*/ /*{{{ Public Global Variables */ int Slrn_Use_Slang = 0; char *Slrn_Macro_Dir; /*}}}*/ static int pop_strings (char **s1p, char **s2p, char **s3p, char **s4p) { char *s1 = NULL, *s2 = NULL, *s3 = NULL, *s4 = NULL; if (s4p != NULL) { if (-1 == SLpop_string (&s4)) return -1; *s4p = s4; } if (s3p != NULL) { if (-1 == SLpop_string (&s3)) goto return_error; *s3p = s3; } if (s2p != NULL) { if (-1 == SLpop_string (&s2)) goto return_error; *s2p = s2; } if (s1p != NULL) { if (-1 == SLpop_string (&s1)) goto return_error; *s1p = s1; } return 0; return_error: slrn_free (s1); slrn_free (s2); slrn_free (s3); slrn_free (s4); return -1; } /*{{{ Screen update and message functions */ static void error (char *msg) /*{{{*/ { slrn_error ("%s", msg); } /*}}}*/ static void update (void) /*{{{*/ { slrn_update_screen (); } /*}}}*/ static void free_argv_list (char **argv, unsigned int argc) { unsigned int i; for (i = 0; i < argc; i++) slrn_free (argv[i]); slrn_free ((char *) argv); } static char **pop_argv_list (unsigned int *argcp) { int n; char **argv; unsigned int i, argc; if (-1 == SLang_pop_integer (&n)) return NULL; if (n < 0) { slrn_error ("positive integer expected"); return NULL; } argc = (unsigned int) n; if (NULL == (argv = (char **) slrn_malloc (sizeof (char *) * (argc + 1), 1, 1))) { SLang_Error = SL_MALLOC_ERROR; return NULL; } argv [n] = NULL; i = argc; while (i != 0) { i--; if (-1 == SLpop_string (argv + i)) { free_argv_list (argv, argc); return NULL; } } *argcp = argc; return argv; } static int interp_select_box (void) /*{{{*/ { unsigned int n; Slrn_Select_Box_Type box; int ret; if (Slrn_Batch) { slrn_error ("select box function not available in batch mode."); return -1; } if (NULL == (box.lines = pop_argv_list (&n))) return -1; if (-1 == SLpop_string (&box.title)) { free_argv_list (box.lines, n); return -1; } ret = slrn_select_box (&box); free_argv_list (box.lines, n); slrn_free (box.title); return ret; } /*}}}*/ static void select_list_box (void) { char *title; unsigned int argc; char **argv; int active; int ret; if (-1 == SLang_pop_integer (&active)) return; argv = pop_argv_list (&argc); if (argv == NULL) return; if (-1 == SLpop_string (&title)) { free_argv_list (argv, argc); return; } ret = slrn_select_list_mode (title, argc, argv, active - 1, NULL); if (ret == -1) { SLang_push_string (""); return; } SLang_push_string (argv[ret]); slrn_free (title); free_argv_list (argv, argc); } static int get_yesno_cancel (char *prompt) { char *p = prompt; /* The slrn_get_response function is sprintf. For that reason, * % cannot be used unless it is doubled up. */ while (NULL != (p = slrn_strchr (p, '%'))) { p++; if (*p != '%') return -1; p++; } return slrn_get_yesno_cancel (prompt); } static int get_response (void) { char *choices, *prompt, *p; int ret; if (-1 == pop_strings (&choices, &prompt, NULL, NULL)) return -1; p = prompt; /* The slrn_get_response function is sprintf. For that reason, * % cannot be used unless it is doubled up. */ while (NULL != (p = slrn_strchr (p, '%'))) { p++; if (*p != '%') { slrn_free (choices); slrn_free (prompt); return -1; } p++; } ret = slrn_get_response (choices, prompt); slrn_free (choices); slrn_free (prompt); return ret; } static void tt_send (void) { char *s; if (-1 == SLpop_string (&s)) return; if (Slrn_Batch == 0) { SLtt_write_string (s); SLtt_flush_output (); } slrn_free (s); } /*}}}*/ /*{{{ File functions */ static void make_home_filename (char *name) /*{{{*/ { char file [SLRN_MAX_PATH_LEN]; slrn_make_home_filename (name, file); SLang_push_string (file); } /*}}}*/ static int evalfile (void) { char *file; if (-1 == SLpop_string (&file)) return -1; if (-1 == slrn_eval_slang_file (file)) { slrn_free (file); return 0; } slrn_free (file); return 1; } int slrn_eval_slang_file (char *name) /*{{{*/ { char file [SLRN_MAX_PATH_LEN]; if (Slrn_Macro_Dir != NULL) { int n = 0; char dir[SLRN_MAX_PATH_LEN]; while (1) { if (-1 == SLextract_list_element (Slrn_Macro_Dir, n, ',', file, sizeof (file))) break; slrn_make_home_dirname (file, dir); if ((-1 != slrn_dircat (dir, name, file)) && (1 == slrn_file_exists (file))) { slrn_message_now ("loading %s", file); if (-1 == SLang_load_file (file)) return -1; return 0; } n++; } } slrn_make_home_filename (name, file); slrn_message_now ("loading %s", file); if (0 == SLang_load_file (file)) return -1; return 0; } /*}}}*/ /*}}}*/ /*{{{ Set/Get Variable Functions */ static void set_string_variable (void) /*{{{*/ { char *s1, *s2; if (-1 == pop_strings (&s1, &s2, NULL, NULL)) return; if (-1 == slrn_set_string_variable (s1, s2)) slrn_error ("%s is not a valid variable name.", s1); slrn_free (s1); slrn_free (s2); } /*}}}*/ static void set_integer_variable (void) /*{{{*/ { char *s1; int val; if (-1 == SLang_pop_integer (&val)) return; if (-1 == SLpop_string (&s1)) return; if (-1 == slrn_set_integer_variable (s1, val)) slrn_error ("%s is not a valid variable name.", s1); slrn_free (s1); } /*}}}*/ static void get_variable_value (void) /*{{{*/ { char *name; char **s; int *ip; int type; if (-1 == SLpop_string (&name)) return; if (-1 == slrn_get_variable_value (name, &type, &s, &ip)) { slrn_error ("%s is not a valid variable name.", name); slrn_free (name); return; } slrn_free (name); if (type == STRING_TYPE) { char *str; if ((s == NULL) || (*s == NULL)) str = ""; else str = *s; SLang_push_string (str); } else if (type == INT_TYPE) { int i; if (ip == NULL) i = 0; else i = *ip; SLang_push_integer (i); } } /*}}}*/ /*}}}*/ static char *get_server_name (void) /*{{{*/ { if ((NULL == Slrn_Server_Obj) || (NULL == Slrn_Server_Obj->sv_name)) return ""; return Slrn_Server_Obj->sv_name; } /*}}}*/ static void quit (int *code) /*{{{*/ { slrn_quit (*code); } /*}}}*/ /*{{{ Keyboard related functions */ static void definekey (char *fun, char *key, char *map) /*{{{*/ { SLKeyMap_List_Type *kmap; if (NULL == (kmap = SLang_find_keymap (map))) { error ("definekey: no such keymap."); return; } if (0 != SLang_define_key (key, fun, kmap)) { } } /*}}}*/ static void undefinekey (char *key, char *map) /*{{{*/ { SLKeyMap_List_Type *kmap; if (NULL == (kmap = SLang_find_keymap (map))) { error ("undefinekey: no such keymap."); return; } SLang_undefine_key (key, kmap); } /*}}}*/ static void generic_read_mini (int no_echo) /*{{{*/ { char str[256]; int ret; char *prompt, *dfl, *init; if (-1 == pop_strings (&prompt, &dfl, &init, NULL)) return; strncpy (str, init, sizeof (str)); str[sizeof(str) - 1] = 0; if (no_echo) ret = slrn_read_input_no_echo (prompt, dfl, str, 0, 0); else ret = slrn_read_input (prompt, dfl, str, 0, 0); slrn_free (init); slrn_free (dfl); slrn_free (prompt); if (-1 == ret) { error ("Quit!"); return; } SLang_push_string (str); } /*}}}*/ static void read_mini (void) /*{{{*/ { generic_read_mini (0); } /*}}}*/ static void read_mini_no_echo (void) /*{{{*/ { generic_read_mini (1); } /*}}}*/ static void set_prefix_arg (int *arg) /*{{{*/ { slrn_set_prefix_argument (*arg); } /*}}}*/ static int check_tty (void) { if (Slrn_TT_Initialized & SLRN_TTY_INIT) return 0; error ("Terminal not initialized."); return -1; } static int input_pending (int *tsecs) { if (check_tty ()) return 0; return SLang_input_pending (*tsecs); } static int getkey (void) { if (check_tty ()) return 0; return SLang_getkey (); } static void ungetkey (int *c) { if (check_tty ()) return; SLang_ungetkey (*c); } static void set_input_string (void) { char *s; if (-1 == SLpop_string (&s)) s = NULL; slrn_set_input_string (s); } static void set_input_chars (void) { char *s; if (-1 == SLpop_string (&s)) s = NULL; slrn_set_input_chars (s); } /*}}}*/ /*{{{ Article Mode Functions */ static int check_article_mode (void) /*{{{*/ { if ((Slrn_Current_Mode == NULL) || (Slrn_Current_Mode->mode != SLRN_ARTICLE_MODE)) { error ("Not in article mode."); return -1; } return 0; } /*}}}*/ static void set_article_window_size (int *nrows) { slrn_set_article_window_size (*nrows); } /*{{{ Article Mode Article Functions */ static void pipe_article_cmd (char *cmd) /*{{{*/ { if (-1 == check_article_mode ()) return; (void) slrn_pipe_article_to_cmd (cmd); } /*}}}*/ static int save_current_article (char *file) /*{{{*/ { if (-1 == check_article_mode ()) return -1; return slrn_save_current_article (file); } /*}}}*/ static int generic_search_article (char *str, int is_regexp) /*{{{*/ { Slrn_Article_Line_Type *l; char *ptr; if (-1 == check_article_mode ()) return 0; l = slrn_search_article (str, &ptr, is_regexp, 1); if (l == NULL) return 0; SLang_push_string (l->buf); return 1; } /*}}}*/ static int search_article (char *s) /*{{{*/ { return generic_search_article (s, 0); } /*}}}*/ static int re_search_article (char *s) /*{{{*/ { return generic_search_article (s, 1); } /*}}}*/ static char *extract_article_header (char *h) /*{{{*/ { unsigned int len; char buf[128]; if (-1 == check_article_mode ()) return NULL; len = strlen (h); if ((len + 3) <= sizeof (buf)) { sprintf (buf, "%s: ", h); h = slrn_extract_header (buf, len + 2); } else h = NULL; if (h == NULL) h = ""; return h; } /*}}}*/ static char *article_as_string (void) /*{{{*/ { unsigned int len; Slrn_Article_Line_Type *l; char *s, *s1; l = Slrn_Article_Lines; len = 0; while (l != NULL) { char *buf; Slrn_Article_Line_Type *next = l->next; buf = l->buf; if (l->flags & WRAPPED_LINE) buf++; /* skip space */ len += strlen (buf); if ((next == NULL) || (0 == (next->flags & WRAPPED_LINE))) len++; l = next; } if (NULL == (s = (char *) SLMALLOC (len + 1))) { SLang_Error = SL_MALLOC_ERROR; return NULL; } l = Slrn_Article_Lines; s1 = s; while (l != NULL) { char *buf; Slrn_Article_Line_Type *next = l->next; buf = l->buf; if (l->flags & WRAPPED_LINE) buf++; /* skip space */ while (*buf != 0) *s1++ = *buf++; if ((next == NULL) || (0 == (next->flags & WRAPPED_LINE))) *s1++ = '\n'; l = next; } *s1 = 0; return s; } /*}}}*/ /*}}}*/ /*{{{ Article Mode Header Functions */ /*{{{ Header Flag Variables */ static int Interp_Header_Read = HEADER_READ; static int Interp_Header_Tagged = HEADER_TAGGED; static int Interp_Header_High_Score = HEADER_HIGH_SCORE; static int Interp_Header_Low_Score = HEADER_LOW_SCORE; /*}}}*/ static void uncollapse_threads (void) /*{{{*/ { if (0 == check_article_mode ()) slrn_uncollapse_threads (1); } /*}}}*/ static void collapse_threads (void) /*{{{*/ { if (0 == check_article_mode ()) slrn_collapse_threads (1); } /*}}}*/ static void collapse_thread (void) { if (0 == check_article_mode ()) slrn_collapse_this_thread (Slrn_Current_Header, 1); } static void uncollapse_thread (void) { if (0 == check_article_mode ()) slrn_uncollapse_this_thread (Slrn_Current_Header, 1); } static int thread_size (void) { if (check_article_mode ()) return -1; return (int) slrn_thread_size (Slrn_Current_Header); } static int is_thread_collapsed (void) { if (check_article_mode ()) return -1; return slrn_is_thread_collapsed (Slrn_Current_Header); } static int header_down (int *num) /*{{{*/ { if ((-1 == check_article_mode ()) || (*num <= 0)) return 0; return slrn_header_down_n (*num, 0); } /*}}}*/ static int header_up (int *num) /*{{{*/ { if ((-1 == check_article_mode ()) || (*num <= 0)) return 0; return slrn_header_up_n (*num, 0); } /*}}}*/ static int header_next_unread (void) { if (-1 == check_article_mode ()) return -1; return slrn_next_unread_header (); } static int get_header_flags (void) /*{{{*/ { if ((-1 == check_article_mode ()) || (Slrn_Current_Header == NULL)) return 0; return (int) (Slrn_Current_Header->flags & HEADER_HARMLESS_FLAGS_MASK); } /*}}}*/ static void set_header_flags (int *flagsp) /*{{{*/ { unsigned int flags; if ((-1 == check_article_mode ()) || (Slrn_Current_Header == NULL)) return; Slrn_Current_Header->flags &= ~HEADER_HARMLESS_FLAGS_MASK; flags = ((unsigned int) *flagsp) & HEADER_HARMLESS_FLAGS_MASK; Slrn_Current_Header->flags |= flags; } /*}}}*/ static int get_header_tag_number (void) { if ((Slrn_Current_Header == NULL) || (0 == (Slrn_Current_Header->flags & HEADER_NTAGGED))) return 0; return (int) Slrn_Current_Header->tag_number; } static void set_header_score (int *score) { (void) slrn_set_header_score (Slrn_Current_Header, *score, 0); } static int get_header_score (void) { if ((-1 == check_article_mode ()) || (Slrn_Current_Header == NULL)) return 0; #if SLRN_HAS_SORT_BY_SCORE return Slrn_Current_Header->score; #else if (Slrn_Current_Header->flags & HEADER_LOW_SCORE) return -1; return 0; #endif } static int get_grouplens_score (void) { if ((-1 == check_article_mode ()) || (Slrn_Current_Header == NULL)) return 0; #if SLRN_HAS_GROUPLENS return Slrn_Current_Header->gl_pred; #else return 0; #endif } /*{{{ Header Searching */ static int re_header_search (char *pat, unsigned int offset, int dir) /*{{{*/ { SLRegexp_Type *re; Slrn_Header_Type *h = Slrn_Current_Header; if ((-1 == check_article_mode ()) || (h == NULL) || (NULL == (re = slrn_compile_regexp_pattern (pat)))) return 0; while (h != NULL) { if (NULL != slrn_regexp_match (re, *(char **) ((char *)h + offset))) { slrn_goto_header (h, 0); return 1; } if (dir > 0) h = h->next; else h = h->prev; } return 0; } /*}}}*/ static int re_subject_search_forward (char *pat) { Slrn_Header_Type h; return re_header_search (pat, (char *) &h.subject - (char *)&h, 1); } static int re_subject_search_backward (char *pat) { Slrn_Header_Type h; return re_header_search (pat, (char *) &h.subject - (char *)&h, -1); } static int re_author_search_forward (char *pat) { Slrn_Header_Type h; return re_header_search (pat, (char *) &h.from - (char *)&h, 1); } static int re_author_search_backward (char *pat) { Slrn_Header_Type h; return re_header_search (pat, (char *) &h.from - (char *)&h, -1); } /*}}}*/ /*}}}*/ /*}}}*/ /*{{{ Group Functions */ static int Interp_Group_Unsubscribed = GROUP_UNSUBSCRIBED; static int Interp_Group_New_Group_Flag = GROUP_NEW_GROUP_FLAG; static int check_group_mode (void) { if ((Slrn_Current_Mode == NULL) || (Slrn_Current_Mode->mode != SLRN_GROUP_MODE)) { error ("Not in group mode."); return -1; } return 0; } static int is_group_mode (void) { return ((Slrn_Current_Mode != NULL) && (Slrn_Current_Mode->mode == SLRN_GROUP_MODE)); } static int group_down_n (int *np) { int n = *np; if (n < 0) return slrn_group_up_n (-n); return slrn_group_down_n (n); } static int group_up_n (int *np) { int n = *np; if (n < 0) return slrn_group_down_n (-n); return slrn_group_up_n (n); } static char *current_group_name (void) { if (Slrn_Group_Current_Group == NULL) return ""; return Slrn_Group_Current_Group->name; } static int get_group_unread_count (void) { if (Slrn_Group_Current_Group == NULL) return 0; return Slrn_Group_Current_Group->unread; } static int select_group (void) { if (-1 == check_group_mode ()) return -1; return slrn_group_select_group (); } static int get_group_flags (void) { if (Slrn_Group_Current_Group == NULL) return 0; return Slrn_Group_Current_Group->flags & GROUP_HARMLESS_FLAGS_MASK; } static void set_group_flags (int *flagsp) { unsigned int flags; if (Slrn_Group_Current_Group == NULL) return; Slrn_Group_Current_Group->flags &= ~GROUP_HARMLESS_FLAGS_MASK; flags = ((unsigned int) *flagsp) & GROUP_HARMLESS_FLAGS_MASK; Slrn_Group_Current_Group->flags |= flags; } /*}}}*/ static void set_color (void) { char *obj; char *fg, *bg; if (-1 == pop_strings (&obj, &fg, &bg, NULL)) return; slrn_set_object_color (obj, fg, bg); slrn_free (obj); slrn_free (fg); slrn_free (bg); } static FILE *Log_File_Ptr; static void close_log_file (void) { if (Log_File_Ptr != NULL) { (void) fclose (Log_File_Ptr); Log_File_Ptr = NULL; } } static void open_log_file (char *file) { close_log_file (); Log_File_Ptr = fopen (file, "w"); if (Log_File_Ptr == NULL) slrn_error ("Unable to open log file %s", file); } static void log_message (char *buf) { FILE *fp; fp = Log_File_Ptr; if (fp == NULL) fp = stderr; fputs (buf, fp); fflush (fp); } static SLang_Intrin_Fun_Type Slrn_Intrinsics [] = /*{{{*/ { MAKE_INTRINSIC_S("open_log_file", open_log_file, SLANG_VOID_TYPE), MAKE_INTRINSIC_0("close_log_file", close_log_file, SLANG_VOID_TYPE), MAKE_INTRINSIC_S("log_message", log_message, SLANG_VOID_TYPE), MAKE_INTRINSIC(".article_as_string", article_as_string, STRING_TYPE, 0), MAKE_INTRINSIC(".call", slrn_call_command, VOID_TYPE, 1), MAKE_INTRINSIC(".collapse_thread", collapse_thread, VOID_TYPE, 0), MAKE_INTRINSIC(".collapse_threads", collapse_threads, VOID_TYPE, 0), MAKE_INTRINSIC(".current_newsgroup", current_group_name, STRING_TYPE, 0), MAKE_INTRINSIC(".definekey", definekey, VOID_TYPE, 3), MAKE_INTRINSIC(".extract_article_header", extract_article_header, STRING_TYPE, 1), MAKE_INTRINSIC(".get_group_flags", get_group_flags, INT_TYPE, 0), MAKE_INTRINSIC(".get_grouplens_score", get_grouplens_score, INT_TYPE, 0), MAKE_INTRINSIC(".get_header_flags", get_header_flags, INT_TYPE, 0), MAKE_INTRINSIC(".get_header_score", get_header_score, INT_TYPE, 0), MAKE_INTRINSIC(".get_header_tag_number", get_header_tag_number, INT_TYPE, 0), MAKE_INTRINSIC(".get_next_art_pgdn_action", slrn_get_next_pagedn_action, INT_TYPE, 0), MAKE_INTRINSIC(".get_response", get_response, INT_TYPE, 0), MAKE_INTRINSIC(".get_select_box_response", interp_select_box, INT_TYPE, 0), MAKE_INTRINSIC(".get_variable_value", get_variable_value, VOID_TYPE, 0), MAKE_INTRINSIC(".get_yes_no_cancel", get_yesno_cancel, INT_TYPE, 1), MAKE_INTRINSIC(".getkey", getkey, INT_TYPE, 0), MAKE_INTRINSIC(".goto_num_tagged_header", slrn_goto_num_tagged_header, INT_TYPE, 1), MAKE_INTRINSIC(".group_down_n", group_down_n, INT_TYPE, 1), MAKE_INTRINSIC(".group_search", slrn_group_search, INT_TYPE, 1), MAKE_INTRINSIC(".group_unread", get_group_unread_count, INT_TYPE, 0), MAKE_INTRINSIC(".group_up_n", group_up_n, INT_TYPE, 1), MAKE_INTRINSIC(".header_down", header_down, INT_TYPE, 1), MAKE_INTRINSIC(".header_next_unread", header_next_unread, INT_TYPE, 0), MAKE_INTRINSIC(".header_up", header_up, INT_TYPE, 1), MAKE_INTRINSIC(".input_pending", input_pending, INT_TYPE, 1), MAKE_INTRINSIC(".is_article_visible", slrn_is_article_visible, INT_TYPE, 0), MAKE_INTRINSIC(".is_group_mode", is_group_mode, INT_TYPE, 0), MAKE_INTRINSIC(".is_thread_collapsed", is_thread_collapsed, INT_TYPE, 0), MAKE_INTRINSIC(".make_home_filename", make_home_filename, VOID_TYPE, 1), MAKE_INTRINSIC(".next_tagged_header", slrn_next_tagged_header, INT_TYPE, 0), MAKE_INTRINSIC(".pipe_article", pipe_article_cmd, VOID_TYPE, 1), MAKE_INTRINSIC(".prev_tagged_header", slrn_prev_tagged_header, INT_TYPE, 0), MAKE_INTRINSIC(".quit", quit, VOID_TYPE, 1), MAKE_INTRINSIC(".re_bsearch_author", re_author_search_backward, INT_TYPE, 1), MAKE_INTRINSIC(".re_bsearch_subject", re_subject_search_backward, INT_TYPE, 1), MAKE_INTRINSIC(".re_fsearch_author", re_author_search_forward, INT_TYPE, 1), MAKE_INTRINSIC(".re_fsearch_subject", re_subject_search_forward, INT_TYPE, 1), MAKE_INTRINSIC(".re_search_article", re_search_article, INT_TYPE, 1), MAKE_INTRINSIC(".read_mini", read_mini, VOID_TYPE, 0), MAKE_INTRINSIC(".read_mini_no_echo", read_mini_no_echo, VOID_TYPE, 0), MAKE_INTRINSIC(".save_current_article", save_current_article, INT_TYPE, 1), MAKE_INTRINSIC(".search_article", search_article, INT_TYPE, 1), MAKE_INTRINSIC(".select_group", select_group, INT_TYPE, 0), MAKE_INTRINSIC(".select_list_box", select_list_box, VOID_TYPE, 0), MAKE_INTRINSIC(".server_name", get_server_name, STRING_TYPE, 0), MAKE_INTRINSIC(".set_article_window_size", set_article_window_size, VOID_TYPE, 1), MAKE_INTRINSIC(".set_color", set_color, VOID_TYPE, 0), MAKE_INTRINSIC(".set_group_flags", set_group_flags, VOID_TYPE, 1), MAKE_INTRINSIC(".set_header_flags", set_header_flags, VOID_TYPE, 1), MAKE_INTRINSIC(".set_header_score", set_header_score, VOID_TYPE, 1), MAKE_INTRINSIC(".set_input_chars", set_input_chars, VOID_TYPE, 0), MAKE_INTRINSIC(".set_input_string", set_input_string, VOID_TYPE, 0), MAKE_INTRINSIC(".set_integer_variable", set_integer_variable, VOID_TYPE, 0), MAKE_INTRINSIC(".set_prefix_argument", set_prefix_arg, VOID_TYPE, 1), MAKE_INTRINSIC(".set_string_variable", set_string_variable, VOID_TYPE, 0), MAKE_INTRINSIC(".thread_size", thread_size, INT_TYPE, 0), MAKE_INTRINSIC(".tt_send", tt_send, VOID_TYPE, 0), MAKE_INTRINSIC(".uncollapse_thread", uncollapse_thread, VOID_TYPE, 0), MAKE_INTRINSIC(".uncollapse_threads", uncollapse_threads, VOID_TYPE, 0), MAKE_INTRINSIC(".undefinekey", undefinekey, VOID_TYPE, 2), MAKE_INTRINSIC(".ungetkey", ungetkey, VOID_TYPE, 1), MAKE_INTRINSIC(".update", update, VOID_TYPE, 0), SLANG_END_TABLE }; /*}}}*/ static SLang_Intrin_Var_Type Intrin_Vars [] = { MAKE_VARIABLE(".GROUPS_DIRTY", &Slrn_Groups_Dirty, INT_TYPE, 1), MAKE_VARIABLE(".GROUP_NEW_GROUP_FLAG", &Interp_Group_New_Group_Flag, INT_TYPE, 1), MAKE_VARIABLE(".GROUP_UNSUBSCRIBED", &Interp_Group_Unsubscribed, INT_TYPE, 1), MAKE_VARIABLE(".HEADER_HIGH_SCORE", &Interp_Header_High_Score, INT_TYPE, 1), MAKE_VARIABLE(".HEADER_LOW_SCORE", &Interp_Header_Low_Score, INT_TYPE, 1), MAKE_VARIABLE(".HEADER_READ", &Interp_Header_Read, INT_TYPE, 1), MAKE_VARIABLE(".HEADER_TAGGED", &Interp_Header_Tagged, INT_TYPE, 1), MAKE_VARIABLE(".SCREEN_HEIGHT", &SLtt_Screen_Rows, INT_TYPE, 1), MAKE_VARIABLE(".SCREEN_WIDTH", &SLtt_Screen_Cols, INT_TYPE, 1), SLANG_END_TABLE }; static int interp_system (char *s) /*{{{*/ { return slrn_posix_system (s, 1); } /*}}}*/ int slrn_init_slang (void) /*{{{*/ { Slrn_Use_Slang = 0; if ((-1 == SLang_init_slang ()) || (-1 == SLang_init_slmath ()) #ifdef __unix__ || (-1 == SLang_init_slunix ()) #endif || (-1 == SLang_init_slfile ()) /* Now add intrinsics for this application */ || (-1 == SLadd_intrin_fun_table(Slrn_Intrinsics, NULL)) || (-1 == SLadd_intrin_var_table(Intrin_Vars, NULL))) return -1; SLadd_intrinsic_function ("system", (FVOID_STAR) interp_system, SLANG_INT_TYPE, 1, SLANG_STRING_TYPE); SLadd_intrinsic_function ("evalfile", (FVOID_STAR) evalfile, SLANG_INT_TYPE, 0); SLang_Error_Hook = error; Slrn_Use_Slang = 1; SLang_User_Clear_Error = slrn_clear_message; SLang_Exit_Error_Hook = slrn_va_exit_error; SLang_Dump_Routine = log_message; return 0; } /*}}}*/ int slrn_reset_slang (void) { close_log_file (); return 0; } #endif