void run_user_flag(char *name, char *what, NickList *user, NickList *kicker) { char *tmp = NULL; char *name_copy, *stuff_copy; int sa = 0; char buffer[BIG_BUFFER_SIZE*5+1]; *buffer = 0; strmopencat(buffer, BIG_BUFFER_SIZE*5, user->nick, space, user->host, space, user->ip, space, user->userlist?one:zero, space, NULL); if (user->userlist) strmopencat(buffer, BIG_BUFFER_SIZE*5, user->userlist->nick, space, user->userlist->host, space, user->userlist->channels, space, ltoa(user->userlist->flags), space, NULL); if (kicker) { strmopencat(buffer, BIG_BUFFER_SIZE*5, kicker->nick, space, kicker->host, space, kicker->ip, space, kicker->userlist?one:zero, NULL); if (kicker->userlist) strmopencat(buffer, BIG_BUFFER_SIZE*5, space, kicker->userlist->nick, space, kicker->userlist->host, space, kicker->userlist->channels, space, ltoa(kicker->userlist->flags), NULL); } if ((tmp = expand_alias(what, empty_string, &sa, NULL))) { stuff_copy = alloca(strlen(tmp) + 1); name_copy = LOCAL_COPY(name); stuff_copy = LOCAL_COPY(tmp); will_catch_return_exceptions++; parse_line(name_copy, stuff_copy, buffer, 0, 0, 1); will_catch_return_exceptions--; return_exception = 0; } new_free(&tmp); }
/* * This is an alternative form of put_it which writes three asterisks * before actually putting things out. */ static void vsay (const char *format, va_list args) { if (window_display && format) { char *str; *putbuf = 0; if ((str = get_string_var(BANNER_VAR))) { if (get_int_var(BANNER_EXPAND_VAR)) { char *foo; foo = expand_alias(str, empty_string); strlcpy(putbuf, foo, sizeof putbuf); new_free(&foo); } else strlcpy(putbuf, str, sizeof putbuf); strlcat(putbuf, " ", sizeof putbuf); } vsnprintf(putbuf + strlen(putbuf), sizeof(putbuf) - strlen(putbuf) - 1, format, args); put_echo(putbuf); } }
/* * add_to_log: add the given line to the log file. If no log file is open * this function does nothing. */ void add_to_log (FILE *fp, long winref, const unsigned char *line, int mangler, const char *rewriter) { char *local_line; size_t size; int must_free = 0; if (!fp || inhibit_logging) return; /* * We need to make a local copy because 'mangle_line' * diddles around with the source, and so we can't subject * line to that, it is 'const'. * * 'mangle_line' can expand the input string, so it is * neccesary to allocate more than we need. */ size = (strlen(line) + 1) * 11; local_line = alloca(size + 1); strlcpy(local_line, line, size + 1); /* Do this first */ if (mangler == 0) mangler = logfile_line_mangler; if (mangler) if (mangle_line(local_line, mangler, size) > size) (void)0; /* Whimper -- what to do, what to do? */ if (get_int_var(NO_CONTROL_LOG_VAR)) { char *tmp = alloca(strlen(local_line) + 1); strip_control(local_line, tmp); strlcpy(local_line, tmp, size); } if (rewriter == NULL) rewriter = get_string_var(LOG_REWRITE_VAR); if (rewriter) { char *prepend_exp; char argstuff[10240]; int args_flag; /* First, create the $* list for the expando */ snprintf(argstuff, 10240, "%ld %s", winref, local_line); /* Now expand the expando with the above $* */ prepend_exp = expand_alias(rewriter, argstuff, &args_flag, NULL); local_line = prepend_exp; must_free = 1; } fprintf(fp, "%s\n", local_line); fflush(fp); if (must_free) new_free(&local_line); }
/* * add_to_log: add the given line to the log file. If no log file is open * this function does nothing. * (Note: "logref" should be -1 unless we are logging from a /log log, ie, * any place that is not inside logfiles.c) */ void add_to_log (int logref, FILE *fp, long winref, const unsigned char *line, int mangler, const char *rewriter) { char *local_line = NULL; int old_logref; static int recursive = 0; /* * I added "recursive" because this function should not * generate any output. But it might generate output if * the string expand was bogus below. I chose to "fix" this * by refusing to log anything recursively. The downside * is any errors won't get logged, which may or may not be * a problem, I haven't decided yet. */ if (recursive > 0) return; if (!fp || inhibit_logging) return; recursive++; old_logref = current_log_refnum; current_log_refnum = logref; /* Do this first */ /* Either do mangling or /set no_control_log, but never both! */ if (mangler == 0) mangler = logfile_line_mangler; else if (get_int_var(NO_CONTROL_LOG_VAR)) mangler |= STRIP_UNPRINTABLE; if (mangler) local_line = new_normalize_string(line, 1, mangler); else local_line = malloc_strdup(line); if (rewriter == NULL) rewriter = get_string_var(LOG_REWRITE_VAR); if (rewriter) { char *prepend_exp; char argstuff[10240]; /* First, create the $* list for the expando */ snprintf(argstuff, 10240, "%ld %s", winref, local_line); new_free(&local_line); /* Now expand the expando with the above $* */ prepend_exp = expand_alias(rewriter, argstuff); local_line = prepend_exp; } fprintf(fp, "%s\n", local_line); fflush(fp); new_free(&local_line); current_log_refnum = old_logref; recursive--; }
void fec(u_char *command, u_char *args, u_char *subargs) { u_char *pointer; u_char *list = NULL; u_char *var = NULL; u_char stuff[2]; int args_flag = 0; unsigned display; u_char *sa, *todo; list = next_expr(&args, '('); /* ) */ if (list == NULL) { yell ("FEC: Missing List for /FEC"); return; } sa = subargs ? subargs : empty_string(); list = expand_alias(NULL, list, sa, &args_flag, NULL); pointer = list; var = next_arg(args, &args); args = my_index(args, '{'); /* } */ if ((todo = next_expr(&args, '{')) == NULL) { yell ("FE: Missing }"); return; } stuff[1] = '\0'; while (*pointer) { display = set_display_off(); stuff[0] = *pointer++; add_alias(VAR_ALIAS, var, stuff); set_display(display); parse_line(NULL, todo, subargs ? subargs : empty_string(), 0, 0, 0); } display = set_display_off(); delete_alias(VAR_ALIAS, var); set_display(display); new_free(&list); }
static void for_fe_cmd (int argc, char **argv, const char *subargs) { char *var, *list, *cmds; char *next, *real_list, *x; if (!subargs) subargs = empty_string; if ((my_stricmp(argv[1], "in")) || (argc != 4)) { my_error("Usage: /FOR var IN (list) {commands}"); return; } var = argv[0]; list = argv[2]; cmds = argv[3]; if (*cmds == '{') cmds++; if (*list == '(') list++; x = real_list = expand_alias(list, subargs); will_catch_break_exceptions++; will_catch_continue_exceptions++; while (real_list && *real_list) { next = next_func_arg(real_list, &real_list); add_local_alias(var, next, 0); runcmds(cmds, subargs); if (break_exception) { break_exception = 0; break; } if (continue_exception) continue_exception = 0; /* Dont continue here! */ if (return_exception) break; if (system_exception) break; } will_catch_break_exceptions--; will_catch_continue_exceptions--; new_free(&x); }
/* * syserr is exactly like say, except that if the error occured while * you were loading a script, it tells you where it happened. */ static void vsyserr (int server, const char *format, va_list args) { char * str; int l, old_from_server = from_server; int i_set_from_server = 0; if (!window_display || !format) return; *putbuf = 0; if ((str = get_string_var(BANNER_VAR))) { if (get_int_var(BANNER_EXPAND_VAR)) { char *foo; foo = expand_alias(str, empty_string); strlcpy(putbuf, foo, sizeof putbuf); new_free(&foo); } else strlcpy(putbuf, str, sizeof putbuf); strlcat(putbuf, " INFO -- ", sizeof putbuf); } vsnprintf(putbuf + strlen(putbuf), sizeof(putbuf) - strlen(putbuf) - 1, format, args); if (is_server_valid(server)) { old_from_server = from_server; from_server = server; i_set_from_server = 1; } l = message_from(NULL, LEVEL_SYSERR); if (do_hook(YELL_LIST, "%s", putbuf)) put_echo(putbuf); pop_message_from(l); if (i_set_from_server) from_server = old_from_server; }
/* * banner: This returns in a static string of either "xxx" where * xxx is the current numeric, or "***" if SHOW_NUMBERS is OFF */ const char * banner (void) { static char thing[80]; char *str; if (current_numeric > 0 && get_int_var(SHOW_NUMERICS_VAR)) snprintf(thing, sizeof thing, "%3.3u", current_numeric); else if ((str = get_string_var(BANNER_VAR))) { if (get_int_var(BANNER_EXPAND_VAR)) { char *foo = expand_alias(str, empty_string); strlcpy(thing, foo, sizeof thing); new_free(&foo); } else strlcpy(thing, str, sizeof thing); } else *thing = 0; return (thing); }
static char input_do_check_prompt(int update) { ScreenInputData *inputdata = screen_get_inputdata(get_current_screen()); u_char *prompt; u_char *ptr; char changed = 0; int free_it = 1; unsigned len; int args_used; /* unused */ if (update == NO_UPDATE) return changed; prompt = prompt_current_prompt(); if (!prompt) prompt = input_prompt ? input_prompt : empty_string(); if (is_process(get_target_by_refnum(0))) { ptr = get_prompt_by_refnum(0); free_it = 0; } else ptr = expand_alias(NULL, prompt, empty_string(), &args_used, NULL); len = my_strlen(ptr); if (my_strncmp(ptr, inputdata->buffer.buf, len) || !len) { input_do_replace_prompt(ptr); changed = 1; } if (free_it) new_free(&ptr); return changed; }
/* * update_input: does varying amount of updating on the input line depending * upon the position of the cursor and the update flag. If the cursor has * move toward one of the edge boundaries on the screen, update_cursor() * flips the input line to the next (previous) line of text. The update flag * may be: * * NO_UPDATE - only do the above bounds checking. * * UPDATE_JUST_CURSOR - do bounds checking and position cursor where is should * be. * * UPDATE_FROM_CURSOR - does all of the above, and makes sure everything from * the cursor to the right edge of the screen is current (by redrawing it). * * UPDATE_ALL - redraws the entire line */ void update_input (int update) { int old_zone; char *ptr, *ptr_free; int len, free_it = 0, max; char *prompt; int do_echo = 1; Screen *os = last_input_screen; Screen *ns; Window *saved_current_window = current_window; /* * No input line in dumb or bg mode. */ if (dumb_mode || !foreground) return; for (ns = screen_list; ns; ns = ns->next) { if (!ns->alive) continue; /* It's dead, Jim! */ last_input_screen = ns; current_window = ns->current_window; /* * Make sure the client thinks the cursor is on the input line. */ cursor_to_input(); /* * See if we're in a add_wait_prompt() call. If we are, grab that * current prompt, otherwise use the default input prompt. */ if (last_input_screen->promptlist) prompt = last_input_screen->promptlist->prompt; else prompt = input_prompt; /* * * GET THE INPUT PROMPT * */ /* * If we have a prompt, and we're supposed to update the input * prompt, then we do need to expand the prompt. */ if (prompt && update != NO_UPDATE) { int af; /* * If the current window is query'ing an exec'd process, * then we just get the current prompt for that process. * Note that it is not malloced. */ if (is_valid_process(get_target_by_refnum(0)) != -1) ptr = get_prompt_by_refnum(0); /* * Otherwise, we just expand the prompt as normal. */ else { ptr = expand_alias(prompt, empty_string, &af, NULL); free_it = 1; } /* * If we're in an add_wait_prompt(), we see whether or not * this is an "invisible" prompt. If it is, we turn off the * echo so what the user types doesnt show up. */ if (last_input_screen->promptlist) term_echo(last_input_screen->promptlist->echo); /* * Mangle out any ansi chars or so forth. */ ptr_free = ptr; ptr = normalize_string(ptr, 0); /* This should be ok */ if (free_it) new_free(&ptr_free); free_it = 1; /* * If the prompt has changed, or if there is no prompt... */ if ( (ptr && !INPUT_PROMPT) || (!ptr && INPUT_PROMPT) || strcmp(ptr, INPUT_PROMPT) ) { if (last_input_screen->input_prompt_malloc) new_free(&INPUT_PROMPT); last_input_screen->input_prompt_malloc = free_it; INPUT_PROMPT = ptr; INPUT_PROMPT_LEN = output_with_count(INPUT_PROMPT, 0, 0); update = UPDATE_ALL; } /* * Prompt didnt change, so clean up our mess */ else { if (free_it) new_free(&ptr); } } /* * * HAS THE SCREEN CHANGED SIZE SINCE THE LAST TIME? * */ /* * If the screen has resized, then we need to re-compute the * side-to-side scrolling effect. */ if ((last_input_screen->li != last_input_screen->old_li) || (last_input_screen->co != last_input_screen->old_co)) { /* * The input line is always the bottom line */ INPUT_LINE = last_input_screen->li - 1; /* * The "zone" is the range in which when you type, the * input line does not scroll. It is WIDTH chars in from * either side of the display. */ ZONE = last_input_screen->co - (WIDTH * 2); if (ZONE < 10) ZONE = 10; /* Take that! */ START_ZONE = WIDTH; END_ZONE = last_input_screen->co - WIDTH; last_input_screen->old_co = last_input_screen->co; last_input_screen->old_li = last_input_screen->li; } /* * About zones: * The input line is divided into "zones". A "zone" is set above, * and is the width of the screen minus 20 (by default). The input * line, as displayed, is therefore composed of the current "zone", * plus 10 characters from the previous zone, plus 10 characters * from the next zone. When the cursor moves to an adjacent zone, * (by going into column 9 from the right or left of the edge), the * input line is redrawn. There is one catch. The first "zone" * includes the first ten characters of the input line. */ old_zone = START_ZONE; /* * The BEGINNING of the current "zone" is a calculated value: * The number of characters since the origin of the input buffer * is the number of printable chars in the input prompt plus the * current position in the input buffer. We subtract from that * the WIDTH delta to take off the first delta, which doesnt * count towards the width of the zone. Then we divide that by * the size of the zone, to get an integer, then we multiply it * back. This gives us the first character on the screen. We * add WIDTH to the result in order to get the start of the zone * itself. * The END of the current "zone" is just the beginning plus the width. * If we have moved to an different "zone" since last time, we want to * completely redraw the input line. */ START_ZONE = ((INPUT_PROMPT_LEN + THIS_POS - WIDTH) / ZONE) * ZONE + WIDTH; END_ZONE = START_ZONE + ZONE; if (old_zone != START_ZONE) update = UPDATE_ALL; /* * Now that we know where the "zone" is in the input buffer, we can * easily calculate where where we want to start displaying stuff * from the INPUT_BUFFER. If we're in the first "zone", then we will * output from the beginning of the buffer. If we're not in the first * "zone", then we will begin to output from 10 characters to the * left of the zone, after adjusting for the length of the prompt. */ if (START_ZONE == WIDTH) INPUT_ONSCREEN = 0; else { if ((INPUT_ONSCREEN = START_ZONE - WIDTH - INPUT_PROMPT_LEN) < 0) INPUT_ONSCREEN = 0; } /* * And the cursor is simply how many characters away THIS_POS is * from the first column on the screen. */ if (INPUT_ONSCREEN == 0) INPUT_CURSOR = INPUT_PROMPT_LEN + THIS_POS; else INPUT_CURSOR = THIS_POS - INPUT_ONSCREEN; /* * If the cursor moved, or if we're supposed to do a full update, * then redraw the entire input line. */ if (update == UPDATE_ALL) { /* * Move the cursor to the start of the input line */ term_move_cursor(0, INPUT_LINE); /* * If the input line is NOT empty, and we're starting the * display at the beginning of the input buffer, then we * output the prompt first. */ if (INPUT_ONSCREEN == 0 && INPUT_PROMPT && *INPUT_PROMPT) { /* * Forcibly turn on echo. */ do_echo = term_echo(1); /* * Crop back the input prompt so it does not extend * past the end of the zone. */ if (INPUT_PROMPT_LEN > (last_input_screen->co - WIDTH)) INPUT_PROMPT_LEN = last_input_screen->co - WIDTH - 1; /* * Output the prompt. */ output_with_count(INPUT_PROMPT, 0, 1); /* * Turn the echo back to what it was before, * and output the rest of the input buffer. */ term_echo(do_echo); safe_puts(INPUT_BUFFER, last_input_screen->co - INPUT_PROMPT_LEN, do_echo); } /* * Otherwise we just output whatever we have. */ else if (do_echo) safe_puts(&(INPUT_VISIBLE), last_input_screen->co, do_echo); /* * Clear the rest of the input line and reset the cursor * to the current input position. */ term_clear_to_eol(); term_move_cursor(INPUT_CURSOR, INPUT_LINE); cursor_not_in_display(last_input_screen); } /* * If we're just supposed to refresh whats to the right of the * current logical position... */ else if (update == UPDATE_FROM_CURSOR) { /* * Move the cursor to where its supposed to be, * Figure out how much we can output from here, * and then output it. */ term_move_cursor(INPUT_CURSOR, INPUT_LINE); max = last_input_screen->co - (THIS_POS - INPUT_ONSCREEN); if (INPUT_ONSCREEN == 0 && INPUT_PROMPT && *INPUT_PROMPT) max -= INPUT_PROMPT_LEN; if ((len = strlen(&(THIS_CHAR))) > max) len = max; safe_puts(&(THIS_CHAR), len, do_echo); term_clear_to_eol(); term_move_cursor(INPUT_CURSOR, INPUT_LINE); cursor_not_in_display(last_input_screen); } /* * If we're just supposed to move the cursor back to the input * line, then go ahead and do that. */ else if (update == UPDATE_JUST_CURSOR) { term_move_cursor(INPUT_CURSOR, INPUT_LINE); cursor_not_in_display(last_input_screen); } /* * Turn the terminal echo back on, and flush all of the output * we may have done here. */ term_echo(1); term_flush(); } last_input_screen = os; current_window = saved_current_window; }
void fe(u_char *command, u_char *args, u_char *subargs) { u_char *list = NULL, *templist = NULL, *placeholder, *oldlist = NULL, *sa, *vars, *var[255], *word = NULL, *todo = NULL; int ind, x, y, count, args_flag; unsigned display; for (x = 0; x < 255; var[x++] = NULL) ; list = next_expr(&args, '('); /* ) */ if (!list) { yell ("FE: Missing List for /FE"); return; } sa = subargs ? subargs : (u_char *) " "; malloc_strcpy(&templist, list); do { malloc_strcpy(&oldlist, templist); new_free(&templist); templist = expand_alias(NULL, oldlist, sa, &args_flag, NULL); } while (my_strcmp(templist, oldlist)); new_free(&oldlist); if (*templist == '\0') { new_free(&templist); return; } vars = args; if (!(args = my_index(args, '{'))) /* } */ { yell ("FE: Missing commands"); new_free(&templist); return; } *(args-1) = '\0'; ind = 0; while ((var[ind++] = next_arg(vars, &vars))) { if (ind == 255) { yell ("FE: Too many variables"); new_free(&templist); return; } } ind = ind ? ind - 1: 0; if (!(todo = next_expr(&args, '{'))) /* } { */ { yell ("FE: Missing }"); new_free(&templist); return; } count = word_count(templist); display = get_display(); placeholder = templist; for (x = 0; x < count;) { set_display_off(); for (y = 0; y < ind; y++) { word = ((x + y) < count) ? next_arg(templist, &templist) : NULL; add_alias(VAR_ALIAS, var[y], word); } set_display(display); x += ind; parse_line(NULL, todo, subargs ? subargs : empty_string(), 0, 0, 0); } set_display_off(); for (y = 0; y < ind; y++) { delete_alias(VAR_ALIAS, var[y]); } set_display(display); new_free(&placeholder); }
/* * update_input: does varying amount of updating on the input line depending * upon the position of the cursor and the update flag. If the cursor has * move toward one of the edge boundaries on the screen, update_cursor() * flips the input line to the next (previous) line of text. The update flag * may be: * * NO_UPDATE - only do the above bounds checking. * * UPDATE_JUST_CURSOR - do bounds checking and position cursor where is should * be. * * UPDATE_FROM_CURSOR - does all of the above, and makes sure everything from * the cursor to the right edge of the screen is current (by redrawing it). * * UPDATE_ALL - redraws the entire line */ void update_input(int update) { int old_start; static int co = 0, li = 0; char *ptr; int len, free_it = 1, cnt, ansi_count, max; char *prompt; cursor_to_input(); if (current_screen->promptlist) prompt = current_screen->promptlist->prompt; else prompt = input_prompt; if (prompt) { if (update != NO_UPDATE) { char *inp_ptr = NULL; int args_used; if (is_process(get_target_by_refnum(0))) { ptr = (char *) get_prompt_by_refnum(0); free_it = 0; } else if (!get_int_var(DISPLAY_ANSI_VAR)) ptr = expand_alias(stripansicodes(prompt), empty_str, &args_used, NULL); else ptr = expand_alias(prompt, empty_str, &args_used, NULL); if (*ptr && ((my_strnicmp(ptr, "Password:"******"Operator Password:"******"Server Password:", 16) == 0))) term_echo(0); else term_echo(1); len = strlen(ptr); if (strncmp(ptr, current_screen->input_buffer, len) || !len) { malloc_strcpy(&inp_ptr, INPUT_BUFFER + MIN_POS); strmcpy(INPUT_BUFFER, ptr, INPUT_BUFFER_SIZE); THIS_POS += (len - MIN_POS); MIN_POS = strlen(ptr); ADD_TO_INPUT(inp_ptr); new_free(&inp_ptr); update = UPDATE_ALL; } if (free_it) new_free(&ptr); } } else term_echo(1); if ((li != term_rows) || (co != term_cols)) { /* resized? Keep it simple and reset everything */ input_line = term_rows - 1; zone = term_cols - (WIDTH * 2) + 4; lower_mark = WIDTH; upper_mark = term_cols - WIDTH; cursor = current_screen->buffer_min_pos; current_screen->buffer_pos = current_screen->buffer_min_pos; str_start = 0; li = term_rows; co = term_cols; } old_start = str_start; ansi_count = count_ansi(current_screen->input_buffer, zone); if (old_ansi != ansi_count || current_screen->buffer_pos - ansi_count > zone) { lower_mark = WIDTH; upper_mark = term_cols - WIDTH; str_start = 0; } ansi_count = count_ansi(&(current_screen->input_buffer[str_start]), zone); while ((current_screen->buffer_pos - ansi_count < lower_mark) && lower_mark > WIDTH) { upper_mark = lower_mark - ansi_count; lower_mark -= (zone + ansi_count); str_start -= (zone + ansi_count); if (str_start < zone) { str_start = 0; ansi_count = count_ansi(&(current_screen->input_buffer[str_start]), zone); lower_mark -= ansi_count; upper_mark -= ansi_count; } } while (current_screen->buffer_pos - ansi_count >= upper_mark) { lower_mark = upper_mark + ansi_count; upper_mark += zone + ansi_count; str_start += zone + ansi_count; if (ansi_count) ansi_count = 0; } /* we need to count ansi characters again, this time in the part of the string we are gonna display in a few moments */ ansi_count = count_ansi(&(current_screen->input_buffer[str_start]), zone); old_ansi = count_ansi(current_screen->input_buffer, zone); /* we need to substract number of ansi characters from cursor position since those are not visible, otherwise we'd display cursor * in wrong place */ cursor = current_screen->buffer_pos - str_start - ansi_count; if ((old_start != str_start) || (update == UPDATE_ALL)) { term_move_cursor(0, input_line); if ((str_start == 0) && (MIN_POS > 0)) { int echo; echo = term_echo(1); if (MIN_POS > (term_cols - WIDTH)) len = term_cols - WIDTH - 1 /* + ansi_count */ ; else len = MIN_POS; cnt = /* term_puts */ safe_puts(&(INPUT_BUFFER[str_start]), len); term_echo(echo); cnt += /* term_puts */ safe_puts(&(current_screen->input_buffer[ str_start + len]), term_cols - len + ansi_count); } else cnt = /* term_puts */ safe_puts(&(INPUT_BUFFER[str_start]), term_cols); term_clear_to_eol(); term_move_cursor(cursor, input_line); } else if (update == UPDATE_FROM_CURSOR) { term_move_cursor(cursor, input_line); cnt = cursor; max = term_cols - (current_screen->buffer_pos - str_start) + ansi_count; if ((len = strlen(&(THIS_CHAR))) > max) len = max; cnt += /* term_puts */ safe_puts(&(THIS_CHAR), len); term_clear_to_eol(); term_move_cursor(cursor, input_line); } else if (update == UPDATE_JUST_CURSOR) term_move_cursor(cursor, input_line); term_flush(); }
/* * This just sucked beyond words. I was always planning on rewriting this, * but the crecendo of complaints with regards to this just got to be too * irritating, so i fixed it early. */ int make_status (Window *window, int must_redraw) { int status_line; u_char buffer [BIG_BUFFER_SIZE + 1]; u_char lhs_buffer [BIG_BUFFER_SIZE + 1]; u_char rhs_buffer [BIG_BUFFER_SIZE + 1]; Char *func_value [MAX_FUNCTIONS]; u_char *ptr; size_t save_size; /* We do NOT redraw status bars for hidden windows */ if (!window->screen || !status_updates_permitted) return -1; for (status_line = 0; status_line < window->status.double_status + 1; status_line++) { u_char lhs_fillchar[6], rhs_fillchar[6], *fillchar = lhs_fillchar, *lhp = lhs_buffer, *rhp = rhs_buffer, *cp, *start_rhs = 0, *str; int in_rhs = 0, pr_lhs = 0, pr_rhs = 0, line, *prc = &pr_lhs, i; fillchar[0] = fillchar[1] = 0; /* * If status line gets to one, then that means that * window->double_status is not zero. That means that * the status line we're working on is STATUS2. */ if (status_line) line = 2; /* * If status_line is zero, and window->double_status is * not zero (double status line is on) then we're working * on STATUS1. */ else if (window->status.double_status) line = 1; /* * So status_line is zero and window->double_status is zero. * So we're working on STATUS (0). */ else line = 0; /* * Sanity check: If the status format doesnt exist, dont do * anything for it. */ if (!window->status.line[line].format) continue; /* * Run each of the status-generating functions from the the * status list. Note that the retval of the functions is no * longer malloc()ed. This saves 40-some odd malloc/free sets * each time the status bar is updated, which is non-trivial. */ for (i = 0; i < MAX_FUNCTIONS; i++) { if (window->screen == NULL) return -1; if (window->status.line[line].func[i] == NULL) panic("status callback null. Window [%d], line [%d], function [%d]", window->refnum, line, i); func_value[i] = window->status.line[line].func[i] (window, window->status.line[line].map[i], window->status.line[line].key[i]); } /* * If the REVERSE_STATUS_LINE var is on, then put a reverse * character in the first position (itll get translated to * the tcap code in the output code. */ if (get_int_var(REVERSE_STATUS_LINE_VAR)) *buffer = REV_TOG , str = buffer + 1; else str = buffer; /* * Now press the status line into "buffer". The magic about * setting status_format is handled elsewhere. */ snprintf(str, BIG_BUFFER_SIZE - 1, window->status.line[line].format, func_value[0], func_value[1], func_value[2], func_value[3], func_value[4], func_value[5], func_value[6], func_value[7], func_value[8], func_value[9], func_value[10], func_value[11], func_value[12], func_value[13], func_value[14], func_value[15], func_value[16], func_value[17], func_value[18], func_value[19], func_value[20], func_value[21], func_value[22], func_value[23], func_value[24], func_value[25], func_value[26], func_value[27], func_value[28], func_value[29], func_value[30], func_value[31], func_value[32], func_value[33], func_value[34], func_value[35], func_value[36], func_value[37], func_value[38], func_value[39]); /* * If the user wants us to, pass the status bar through the * expander to pick any variables/function calls. * This is horribly expensive, but what do i care if you * want to waste cpu cycles? ;-) */ if (get_int_var(STATUS_DOES_EXPANDOS_VAR)) { int af = 0; int old_fs = from_server; Window *old = current_window; int owd = window_display; current_window = window; from_server = current_window->server; window_display = 0; str = expand_alias(buffer, empty_string, &af, NULL); window_display = owd; from_server = old_fs; current_window = old; strlcpy(buffer, str, sizeof buffer); new_free(&str); } /* * This converts away any ansi codes in the status line * in accordance with the currenet settings. This leaves us * with nothing but logical characters, which are then easy * to count. :-) */ str = normalize_string(buffer, 3); /* * Count out the characters. * Walk the entire string, looking for nonprintable * characters. We count all the printable characters * on both sides of the %> tag. */ ptr = str; cp = lhp; lhs_buffer[0] = rhs_buffer[0] = 0; while (*ptr) { /* * The FIRST such %> tag is used. * Using multiple %>s is bogus. */ if (*ptr == '\f' && start_rhs == NULL) { ptr++; start_rhs = ptr; fillchar = rhs_fillchar; in_rhs = 1; *cp = 0; cp = rhp; prc = &pr_rhs; } /* * Skip over attribute changes, not useful. */ else if (*ptr == '\006') { /* Copy the next 5 values */ *cp++ = *ptr++; *cp++ = *ptr++; *cp++ = *ptr++; *cp++ = *ptr++; *cp++ = *ptr++; } /* * XXXXX This is a bletcherous hack. * If i knew what was good for me id not do this. */ else if (*ptr == 9) /* TAB */ { fillchar[0] = ' '; fillchar[1] = 0; do *cp++ = ' '; while (++(*prc) % 8); ptr++; } /* * So it is a printable character. */ else { *prc += 1; fillchar[0] = *cp++ = *ptr++; fillchar[1] = 0; } /* * Dont allow more than CO printable characters */ if (pr_lhs + pr_rhs >= window->screen->co) { *cp = 0; break; } } *cp = 0; /* What will we be filling with? */ if (get_int_var(STATUS_NO_REPEAT_VAR)) { lhs_fillchar[0] = ' '; lhs_fillchar[1] = 0; rhs_fillchar[0] = ' '; rhs_fillchar[1] = 0; } /* * Now if we have a rhs, then we have to adjust it. */ if (start_rhs) { int numf = 0; numf = window->screen->co - pr_lhs - pr_rhs -1; while (numf-- >= 0) strlcat(lhs_buffer, lhs_fillchar, sizeof lhs_buffer); } /* * No rhs? If the user wants us to pad it out, do so. */ else if (get_int_var(FULL_STATUS_LINE_VAR)) { int chars = window->screen->co - pr_lhs - 1; while (chars-- >= 0) strlcat(lhs_buffer, lhs_fillchar, sizeof lhs_buffer); } save_size = strlen(all_off()); strlcpy(buffer, lhs_buffer, sizeof buffer - save_size); strlcat(buffer, rhs_buffer, sizeof buffer - save_size); strlcat(buffer, all_off(), sizeof buffer); new_free(&str); /* * Ends up that BitchX always throws this hook and * people seem to like having this thrown in standard * mode, so i'll go along with that. */ do_hook(STATUS_UPDATE_LIST, "%d %d %s", window->refnum, status_line, buffer); if (dumb_mode || !foreground) continue; /* * Update the status line on the screen. * First check to see if it has changed * Remember this is only done in full screen mode. */ if (must_redraw || !window->status.line[status_line].result || strcmp(buffer, window->status.line[status_line].result)) { /* * Roll the new back onto the old */ malloc_strcpy(&window->status.line[status_line].result, buffer); /* * Output the status line to the screen */ output_screen = window->screen; term_move_cursor(0, window->bottom + status_line); output_with_count(buffer, 1, 1); cursor_in_display(window); } } cursor_to_input(); return 0; }