static void toc_header(struct buf *ob, const struct buf *text, int level, void *opaque) { struct html_renderopt *options = opaque; if (level <= options->toc_data.nesting_level) { /* set the level offset if this is the first header * we're parsing for the document */ if (options->toc_data.current_level == 0) options->toc_data.level_offset = level - 1; level -= options->toc_data.level_offset; if (level > options->toc_data.current_level) { while (level > options->toc_data.current_level) { BUFPUTSL(ob, "<ul>\n<li>\n"); options->toc_data.current_level++; } } else if (level < options->toc_data.current_level) { BUFPUTSL(ob, "</li>\n"); while (level < options->toc_data.current_level) { BUFPUTSL(ob, "</ul>\n</li>\n"); options->toc_data.current_level--; } BUFPUTSL(ob,"<li>\n"); } else { BUFPUTSL(ob,"</li>\n<li>\n"); } bufprintf(ob, "<a href=\"#%s\">", header_anchor(text)); if (text) { if (options->flags & HTML_ESCAPE) escape_html(ob, text->data, text->size); else bufput(ob, text->data, text->size); } BUFPUTSL(ob, "</a>\n"); } }
static void toc_header(struct buf *ob, const struct buf *text, int level, void *opaque) { struct html_renderopt *options = opaque; /* set the level offset if this is the first header * we're parsing for the document */ if (options->toc_data.current_level == 0) { BUFPUTSL(ob, "<div class=\"toc\">\n"); options->toc_data.level_offset = level - 1; } level -= options->toc_data.level_offset; if (level > options->toc_data.current_level) { while (level > options->toc_data.current_level) { BUFPUTSL(ob, "<ul>\n<li>\n"); options->toc_data.current_level++; } } else if (level < options->toc_data.current_level) { BUFPUTSL(ob, "</li>\n"); while (level < options->toc_data.current_level) { BUFPUTSL(ob, "</ul>\n</li>\n"); options->toc_data.current_level--; } BUFPUTSL(ob,"<li>\n"); } else { BUFPUTSL(ob,"</li>\n<li>\n"); } BUFPUTSL(ob, "<a href=\"#"); if (options->toc_id_prefix) { bufputs(ob, options->toc_id_prefix); } bufprintf(ob, "toc_%d\">", options->toc_data.header_count++); if (text) escape_html(ob, text->data, text->size); BUFPUTSL(ob, "</a>\n"); }
static void nat_paragraph(struct buf *ob, struct buf *text, void *opaque) { size_t i = 0; if (ob->size) bufputc(ob, '\n'); BUFPUTSL(ob, "<p"); if (text && text->size && text->data[0] == '(') { i = 1; while (i < text->size && (text->data[i] == ' ' /* this seems to be a bit more restrictive than */ /* what is allowed for class names */ || (text->data[i] >= 'a' && text->data[i] <= 'z') || (text->data[i] >= 'A' && text->data[i] <= 'Z') || (text->data[i] >= '0' && text->data[i] <= '0'))) i += 1; if (i < text->size && text->data[i] == ')') { bufprintf(ob, " class=\"%.*s\"", (int)(i - 1), text->data + 1); i += 1; } else i = 0; } bufputc(ob, '>'); if (text) bufput(ob, text->data + i, text->size - i); BUFPUTSL(ob, "</p>\n"); }
unsigned long get_mail_top(char *username) { char buf[MAX_PATHLEN], *p; DIR *dirp; struct dirent *direntp; unsigned long maxnum = 0UL, n; bufprintf(buf, sizeof(buf), "%s/%c/%s/", PARAM_USERDIR, *username, username); path_strip(buf); if ((dirp = opendir(buf)) == NULL) return maxnum; while((direntp = readdir(dirp)) != NULL) { p = direntp->d_name; if (*p >= '0' && *p <= '9') { n = cstrtoul(p, 10); if (n > maxnum) maxnum = n; } } closedir(dirp); return maxnum; }
/* rm -rf : first empty directory, then remove directory */ int rm_rf_trashdir(char *dirname) { char buf[MAX_PATHLEN], *bufp; DIR *dirp; struct dirent *direntp; if (dirname == NULL || !*dirname) return -1; /* safety check */ bufprintf(buf, sizeof(buf), "%s/", PARAM_TRASHDIR); path_strip(buf); if (strncmp(buf, dirname, strlen(buf)) || cstrstr(dirname, "..") != NULL) return -1; cstrcpy(buf, dirname, MAX_PATHLEN); bufp = buf+strlen(buf)-1; if (*bufp != '/') { bufp++; *bufp = '/'; bufp++; *bufp = 0; } if ((dirp = opendir(buf)) == NULL) return -1; while((direntp = readdir(dirp)) != NULL) { /* check for '.' and '..' directory */ if (direntp->d_name[0] == '.' && (!direntp->d_name[1] || (direntp->d_name[1] == '.' && !direntp->d_name[2]))) continue; cstrcpy(bufp, direntp->d_name, MAX_PATHLEN); unlink(buf); /* note: trash/ is not cached ; it's ok not to use unlink_file() */ } closedir(dirp); return remove_dir(dirname); }
static void toc_header(struct buf *ob, struct buf *text, int level, void *opaque) { struct html_renderopt *options = opaque; while (level > options->toc_data.current_level) { if (options->toc_data.current_level > 0) BUFPUTSL(ob, "<li>"); BUFPUTSL(ob, "<ul>\n"); options->toc_data.current_level++; } while (level < options->toc_data.current_level) { BUFPUTSL(ob, "</ul>"); if (options->toc_data.current_level > 1) BUFPUTSL(ob, "</li>\n"); options->toc_data.current_level--; } bufprintf(ob, "<li><a href=\"#toc_%d\">", options->toc_data.header_count++); if (text) bufput(ob, text->data, text->size); BUFPUTSL(ob, "</a></li>\n"); }
static void nat_span(struct buf *ob, struct buf *text, char *tag) { bufprintf(ob, "<%s>", tag); bufput(ob, text->data, text->size); bufprintf(ob, "</%s>", tag); }
static void rndr_header(struct buf *ob, struct buf *text, int level, void *opaque) { if (ob->size) bufputc(ob, '\n'); bufprintf(ob, "<h%d>", level); if (text) bufput(ob, text->data, text->size); bufprintf(ob, "</h%d>\n", level); }
/* convert key code to long color code some key codes do not have a long equivalent flags can be USR_SHORT_DL_COLORS, which means that the color codes should be represented in short format */ int short_color_to_long(char c, char *buf, int max_len, int flags) { int i; if (buf == NULL || max_len <= 0) return -1; buf[0] = 0; switch(c) { case KEY_CTRL('Q'): /* don't auto-color this string */ break; case KEY_CTRL('X'): break; case KEY_CTRL('A'): cstrcpy(buf, "<beep>", max_len); break; case KEY_CTRL('L'): /* clear screen */ break; case KEY_CTRL('Z'): case KEY_CTRL('R'): case KEY_CTRL('G'): case KEY_CTRL('Y'): case KEY_CTRL('B'): case KEY_CTRL('M'): case KEY_CTRL('C'): case KEY_CTRL('W'): for(i = 0; i < NUM_COLORS; i++) { if (color_table[i].key == c) { if (flags & USR_SHORT_DL_COLORS) { /* black is Ctrl-Z, but actually has to entered as Ctrl-K see also edit_color() in edit.c (this is confusing, but black is blacK, while the K is for hotkeys) */ if (c == KEY_CTRL('Z')) c = KEY_CTRL('K'); bufprintf(buf, max_len, "^%c", c + 'A' - 1); } else { bufprintf(buf, max_len, "<%s>", color_table[i].name); cstrlwr(buf); } break; } } break; case KEY_CTRL('K'): cstrcpy(buf, "<hotkey>", max_len); break; case KEY_CTRL('N'): cstrcpy(buf, "<normal>", max_len); break; case KEY_CTRL('D'): cstrcpy(buf, "<default>", max_len); break; default: if (c >= ' ' && c <= '~' && max_len >= 2) { buf[0] = c; buf[1] = 0; } } return 0; }
/* - it takes the cursor position into account for <hline> and <center> tags - when max_lines > -1, can display a limited number of lines (used in --More-- prompt reading) - returns position in the string where it stopped - if dev is NULL, it produces no output, but does run the function and update the cursor pos - force_auto_color_off is used for hline tags, that really don't like auto-coloring - is_symbol says if it's a symbol that needs auto-coloring - dont_auto_color is for controlling exceptions to the rule of auto-coloring */ int Out_text(StringIO *dev, User *usr, char *str, int *cpos, int *lines, int max_lines, int force_auto_color_off) { char buf[MAX_COLORBUF], c; int pos, n, dont_auto_color, color, is_symbol; if (usr == NULL || usr->display == NULL || str == NULL || cpos == NULL || lines == NULL) return 0; if (max_lines > -1 && *lines >= max_lines) return 0; dont_auto_color = force_auto_color_off; pos = 0; while(*str) { is_symbol = 0; pos++; c = *str; if ((usr->flags & USR_HACKERZ) && HACK_CHANCE) c = hackerz_mode(c); /* user-defined auto-coloring symbols */ if ((usr->flags & (USR_ANSI|USR_DONT_AUTO_COLOR)) == USR_ANSI) { char *symbol_str; symbol_str = (usr->symbols == NULL) ? Default_Symbols : usr->symbols; if (cstrchr(symbol_str, c) != NULL) { is_symbol = 1; /* auto-coloring a single dot is ugly, but multiple ones is fun */ if (c == '.' && str[1] != '.' && (pos > 0 && str[-1] != '.')) dont_auto_color = AUTO_COLOR_FORCED; } } /* word-wrap in display function Charset1 contains characters that break the line */ if (cstrchr(Wrap_Charset1, c) != NULL) { if (*cpos + word_len(str+1) >= usr->display->term_width) { if (c != ' ') { if (is_symbol && !dont_auto_color) { auto_color(usr, buf, MAX_COLORBUF); put_StringIO(dev, buf); } write_StringIO(dev, str, 1); if (is_symbol && !dont_auto_color) { restore_colorbuf(usr, usr->color, buf, MAX_COLORBUF); put_StringIO(dev, buf); } } if (str[1] == ' ') { str++; pos++; } put_StringIO(dev, "\r\n"); *cpos = 0; (*lines)++; if (max_lines > -1 && *lines >= max_lines) return pos; dont_auto_color = force_auto_color_off; if (*str) str++; continue; } } else { /* pretty word-wrap: Charset2 contains characters that wrap along with the line mind that the < character is also used for long color codes */ if (c != '<' && cstrchr(Wrap_Charset2, c) != NULL) { if (*cpos + word_len(str+1) >= usr->display->term_width) { write_StringIO(dev, "\r\n", 2); *cpos = 0; (*lines)++; if (max_lines > -1 && *lines >= max_lines) return pos-1; dont_auto_color = force_auto_color_off; } } } switch(c) { case '\b': write_StringIO(dev, "\b", 1); if (*cpos) (*cpos)--; dont_auto_color = force_auto_color_off; break; case '\n': write_StringIO(dev, "\r\n", 2); *cpos = 0; (*lines)++; if (max_lines > -1 && *lines >= max_lines) return pos; dont_auto_color = force_auto_color_off; break; case KEY_CTRL('Q'): /* don't auto-color this string */ dont_auto_color = AUTO_COLOR_FORCED; break; case KEY_CTRL('X'): write_StringIO(dev, "\r", 1); *cpos = 0; dont_auto_color = force_auto_color_off; break; case KEY_CTRL('A'): if (usr->flags & USR_BEEP) write_StringIO(dev, "\a", 1); dont_auto_color = force_auto_color_off; break; case KEY_CTRL('L'): /* clear screen */ if (usr->flags & (USR_ANSI|USR_BOLD)) write_StringIO(dev, "\x1b[1;1H\x1b[2J", 10); break; case KEY_CTRL('Z'): case KEY_CTRL('R'): case KEY_CTRL('G'): case KEY_CTRL('Y'): case KEY_CTRL('B'): case KEY_CTRL('M'): case KEY_CTRL('C'): case KEY_CTRL('W'): /* case KEY_CTRL('F'): */ if (usr->flags & USR_ANSI) { usr->color = c; color = Ansi_Color(usr, c); if (usr->flags & USR_BOLD) bufprintf(buf, sizeof(buf), "\x1b[1;%dm", color); else bufprintf(buf, sizeof(buf), "\x1b[%dm", color); put_StringIO(dev, buf); dont_auto_color = AUTO_COLOR_FORCED; } break; case KEY_CTRL('K'): str++; if (!*str) break; print_hotkey(usr, *str, buf, sizeof(buf), cpos); put_StringIO(dev, buf); dont_auto_color = force_auto_color_off; break; case KEY_CTRL('N'): if (usr->flags & USR_ANSI) { bufprintf(buf, sizeof(buf), "\x1b[0;%dm", color_table[usr->colors[BACKGROUND]].value+10); put_StringIO(dev, buf); } else if (usr->flags & USR_BOLD) put_StringIO(dev, "\x1b[0m"); if (usr->flags & USR_BOLD) put_StringIO(dev, "\x1b[1m"); dont_auto_color = force_auto_color_off; break; case KEY_CTRL('D'): if (usr->flags & (USR_ANSI | USR_BOLD)) put_StringIO(dev, "\x1b[0m"); dont_auto_color = force_auto_color_off; break; /* long codes are specified as '<yellow>', '<beep>', etc. */ case '<': n = long_color_code(dev, usr, str, cpos, lines, max_lines, dont_auto_color); if (n > 0) dont_auto_color = AUTO_COLOR_FORCED; str += n; pos += n; break; default: if (is_symbol && !dont_auto_color) { auto_color(usr, buf, MAX_COLORBUF); put_StringIO(dev, buf); } write_StringIO(dev, &c, 1); (*cpos)++; if (is_symbol && !dont_auto_color) { restore_colorbuf(usr, usr->color, buf, MAX_COLORBUF); put_StringIO(dev, buf); } if (!is_symbol) dont_auto_color = force_auto_color_off; } if (*str) str++; } /* Flush(usr); the buffering code and mainloop() will flush for us */ return pos; }
/* find_Room() with abbreviated name */ Room *find_abbrevRoom(User *usr, char *name) { Room *r; char room_name[MAX_LINE+2], match[MAX_LINE+2]; if (name == NULL || !*name || usr == NULL) return NULL; if ((r = find_Room(usr, name)) == NULL) { int l; l = strlen(name); for(r = AllRooms; r != NULL; r = r->next) { if (!strncmp(r->name, name, l)) { if (r->number == LOBBY_ROOM || r->number == MAIL_ROOM || r->number == HOME_ROOM) return find_Roombynumber(usr, r->number); if (!room_visible(usr, r)) continue; if (!PARAM_HAVE_CHATROOMS && (r->flags & ROOM_CHATROOM)) continue; return r; } } /* didn't find any room, try a substring that matches whole words */ bufprintf(match, sizeof(match), " %s ", name); for(r = AllRooms; r != NULL; r = r->next) { bufprintf(room_name, sizeof(room_name), " %s ", r->name); if (cstrstr(room_name, match) != NULL) { if (r->number == LOBBY_ROOM || r->number == MAIL_ROOM || r->number == HOME_ROOM) return find_Roombynumber(usr, r->number); if (!room_visible(usr, r)) continue; if (!PARAM_HAVE_CHATROOMS && (r->flags & ROOM_CHATROOM)) continue; return r; } } /* didn't find any room, try a substring that matches half words */ for(r = AllRooms; r != NULL; r = r->next) { if (cstrstr(r->name, name) != NULL) { if (r->number == LOBBY_ROOM || r->number == MAIL_ROOM || r->number == HOME_ROOM) return find_Roombynumber(usr, r->number); if (!room_visible(usr, r)) continue; if (!PARAM_HAVE_CHATROOMS && (r->flags & ROOM_CHATROOM)) continue; return r; } } return NULL; } return r; }
/* prints the entries in raw_list to create a menu in columns this routine looks a lot like the one that formats the wide who-list flags is FORMAT_NUMBERED|FORMAT_NO_UNDERSCORES */ void print_columns(User *usr, StringList *raw_list, int flags) { int term_width, total, cols, rows, i, j, buflen, len, max_width, idx; StringList *sl, *sl_cols[16]; char buf[MAX_LINE*4], format[MAX_LINE], filename[MAX_PATHLEN], *p; if (usr == NULL || raw_list == NULL) return; term_width = usr->display->term_width; if (term_width >= MAX_LONGLINE) term_width = MAX_LONGLINE; total = 0; max_width = 10; for(sl = raw_list; sl != NULL; sl = sl->next) { len = strlen(sl->str); if (len > max_width) max_width = len; total++; } if (flags & FORMAT_NUMBERED) bufprintf(format, sizeof(format), "%c%%3d %c%%-%ds", (char)color_by_name("green"), (char)color_by_name("yellow"), max_width); else bufprintf(format, sizeof(format), "%c%%-%ds", (char)color_by_name("yellow"), max_width); cols = term_width / (max_width+6); if (cols < 1) cols = 1; else if (cols > 15) cols = 15; rows = total / cols; if (total % cols) rows++; memset(sl_cols, 0, sizeof(StringList *) * cols); /* fill in array of pointers to columns */ sl = raw_list; for(i = 0; i < cols; i++) { sl_cols[i] = sl; for(j = 0; j < rows; j++) { if (sl == NULL) break; sl = sl->next; } } /* make the menu text */ for(j = 0; j < rows; j++) { idx = j + 1; buf[0] = 0; buflen = 0; for(i = 0; i < cols; i++) { if (sl_cols[i] == NULL || sl_cols[i]->str == NULL) continue; cstrcpy(filename, sl_cols[i]->str, MAX_PATHLEN); if (flags & FORMAT_NO_UNDERSCORES) { p = filename; while((p = cstrchr(p, '_')) != NULL) *p = ' '; } if (flags & FORMAT_NUMBERED) buflen += bufprintf(buf+buflen, sizeof(buf) - buflen, format, idx, filename); else buflen += bufprintf(buf+buflen, sizeof(buf) - buflen, format, filename); idx += rows; if ((i+1) < cols) { buf[buflen++] = ' '; buf[buflen++] = ' '; buf[buflen] = 0; } sl_cols[i] = sl_cols[i]->next; } buf[buflen++] = '\n'; buf[buflen] = 0; Put(usr, buf); } }
/* TODO: accuracy */ int ranged_attack( entity_t *atk, int tx, int ty ) { weapon_t *wpn; int cx = atk->x, cy = atk->y; if( !atk->in_hand ) { if( atk == player ) { buf_t *msg = bufnew( "You're not wielding anything!" ); push_message( msg ); bufdestroy( msg ); } return 0; } if( atk->in_hand->type != ITEMTYPE_WEAPON ) { if( atk == player ) { buf_t *msg = bufnew( "You're not wielding a weapon!" ); push_message( msg ); bufdestroy( msg ); } return 0; } wpn = (weapon_t*)atk->in_hand->specific; if( wpn->type != WEAPONTYPE_HANDGUN ) { if( atk == player ) { buf_t *msg = bufnew( "You're not wielding a ranged weapon!" ); push_message( msg ); bufdestroy( msg ); } return 0; } /* consume ammo */ if( wpn->ammo_loaded >= 1 ) { wpn->ammo_loaded -= 1; } else { buf_t *msg = bufnew( "The clip is empty!" ); push_message( msg ); bufdestroy( msg ); return 0; } if( atk == player ) { buf_t *msg = bufnew( "You shoot your weapon!" ); push_message( msg ); bufdestroy( msg ); } while( 1 ) { cx += tx; cy += ty; if( is_legal( cx, cy ) && ( dungeon[atk->z]->terrain[cx][cy]->flags & TILEFLAG_SOLID ) ) { /* you hit something solid */ break; } attrset( COLOR_PAIR( C_RED ) ); mvaddch( cy+2, cx, '*' ); entity_t *e = entity_find_by_position( cx, cy, atk->z ); if( e ) { buf_t *msg = bufprintf( "You hit the %s!", e->name->data ); push_message( msg ); bufdestroy( msg ); take_damage( e, wpn ); break; } } refresh(); msleep( 100 ); return 1; }
int melee_attack( entity_t *atk, entity_t *def ) { if( !atk->in_hand ) { if( atk == player ) { buf_t *msg = bufprintf( "You %s the %s.", atk->natural->attack_name, def->name->data ); push_message( msg ); bufdestroy( msg ); } else if( def == player ) { buf_t *msg = bufprintf( "The %s %ss you.", atk->name->data, atk->natural->attack_name ); push_message( msg ); bufdestroy( msg ); } take_damage( def, atk->natural ); return 1; } if( atk->in_hand->type != ITEMTYPE_WEAPON ) { if( atk == player ) { buf_t *msg = bufnew( "You're not wielding a weapon." ); push_message( msg ); bufdestroy( msg ); } return 0; } weapon_t *wpn = (weapon_t*)atk->in_hand->specific; if( wpn->type != WEAPONTYPE_MELEE ) { /* TODO: ranged weapons that also have melee attacks? */ if( atk == player ) { buf_t *msg = bufnew( "You're not wielding a melee weapon." ); push_message( msg ); bufdestroy( msg ); } return 0; } if( atk == player ) { buf_t *msg = bufprintf( "You hit the %s!", def->name->data ); push_message( msg ); bufdestroy( msg ); } else if( def == player ) { buf_t *msg = bufprintf( "The %s hits you!", atk->name->data ); push_message( msg ); bufdestroy( msg ); } take_damage( def, wpn ); return 1; }
static int rndr_footnote_ref(struct buf *ob, unsigned int num, void *opaque) { bufprintf(ob, "<sup id=\"fnref%d\"><a href=\"#fn%d\" rel=\"footnote\">%d</a></sup>", num, num, num); return 1; }
/* long color codes look like '<yellow>', '<white>', '<hotkey>', etc. parsing the long color code is a slow function... but it makes programming with color coded strings a lot easier task it's more or less sorted in order of most frequent appearance to make it less slow cpos is the cursor position, which is used in <hline> and <center> tags for <hline>, the function recurses with Out_text() if dev is NULL, it produces no output */ int long_color_code(StringIO *dev, User *usr, char *code, int *cpos, int *lines, int max_lines, int dont_auto_color) { int i, c, color; char colorbuf[MAX_COLORBUF], buf[PRINT_BUF], *p; if (usr == NULL || code == NULL || !*code || cpos == NULL || lines == NULL) return 0; for(i = 0; i < NUM_COLORS; i++) { if (i == HOTKEY) continue; bufprintf(colorbuf, sizeof(colorbuf), "<%s>", color_table[i].name); if (!cstrnicmp(code, colorbuf, strlen(colorbuf))) { if (!(usr->flags & USR_ANSI)) return strlen(colorbuf)-1; c = usr->color = color_table[i].key; color = Ansi_Color(usr, c); if (usr->flags & USR_BOLD) bufprintf(buf, sizeof(buf), "\x1b[1;%dm", color); else bufprintf(buf, sizeof(buf), "\x1b[%dm", color); put_StringIO(dev, buf); return strlen(colorbuf)-1; } } /* Blinking is really irritating... if (!cstrnicmp(code, "<flash>", 7) || !cstrnicmp(code, "<blink>", 7)) { if (!(usr->flags & USR_ANSI)) return 6; usr->color = KEY_CTRL('F'); color = Ansi_Color(usr, KEY_CTRL('F')); if (usr->flags & USR_BOLD) bufprintf(buf, sizeof(buf), "\x1b[1;%dm", color); else bufprintf(buf, sizeof(buf), "\x1b[%dm", color); put_StringIO(dev, buf); return 6; } */ if (!cstrnicmp(code, "<hotkey>", 8)) { c = code[8]; if (!c) return 7; print_hotkey(usr, c, buf, sizeof(buf), cpos); put_StringIO(dev, buf); return 8; } if (!cstrnicmp(code, "<key>", 5)) { c = code[5]; if (!c) return 4; /* Don't do this; the <key> code is used in the Help files to keep this from happening if (usr->flags & USR_UPPERCASE_HOTKEYS) c = ctoupper(c); */ if (usr->flags & USR_ANSI) { if (usr->flags & USR_BOLD) bufprintf(buf, sizeof(buf), "\x1b[1;%dm%c\x1b[1;%dm", color_table[usr->colors[HOTKEY]].value, c, Ansi_Color(usr, usr->color)); else bufprintf(buf, sizeof(buf), "\x1b[%dm%c\x1b[%dm", color_table[usr->colors[HOTKEY]].value, c, Ansi_Color(usr, usr->color)); (*cpos)++; } else { bufprintf(buf, sizeof(buf), "<%c>", c); *cpos += 3; } put_StringIO(dev, buf); return 5; } if (!cstrnicmp(code, "<beep>", 6)) { if (usr->flags & USR_BEEP) write_StringIO(dev, "\a", 1); return 5; } if (!cstrnicmp(code, "<normal>", 8)) { if (usr->flags & USR_ANSI) { bufprintf(buf, sizeof(buf), "\x1b[0;%dm", color_table[usr->colors[BACKGROUND]].value+10); put_StringIO(dev, buf); } else if (usr->flags & USR_BOLD) put_StringIO(dev, "\x1b[0m"); if (usr->flags & USR_BOLD) put_StringIO(dev, "\x1b[1m"); return 7; } if (!cstrnicmp(code, "<default>", 9)) { if (usr->flags & (USR_ANSI | USR_BOLD)) put_StringIO(dev, "\x1b[0m"); return 8; } if (!cstrnicmp(code, "<lt>", 4)) { if ((usr->flags & USR_ANSI) && !(usr->flags & USR_DONT_AUTO_COLOR) && !dont_auto_color) { auto_color(usr, colorbuf, MAX_COLORBUF); put_StringIO(dev, colorbuf); } write_StringIO(dev, "<", 1); (*cpos)++; if ((usr->flags & USR_ANSI) && !(usr->flags & USR_DONT_AUTO_COLOR) && !dont_auto_color) { restore_colorbuf(usr, usr->color, colorbuf, MAX_COLORBUF); put_StringIO(dev, colorbuf); } return 3; } if (!cstrnicmp(code, "<gt>", 4)) { if ((usr->flags & USR_ANSI) && !(usr->flags & USR_DONT_AUTO_COLOR) && !dont_auto_color) { auto_color(usr, colorbuf, MAX_COLORBUF); put_StringIO(dev, colorbuf); } write_StringIO(dev, ">", 1); (*cpos)++; if ((usr->flags & USR_ANSI) && !(usr->flags & USR_DONT_AUTO_COLOR) && !dont_auto_color) { restore_colorbuf(usr, usr->color, colorbuf, MAX_COLORBUF); put_StringIO(dev, colorbuf); } return 3; } /* there are two special codes for use in help files and stuff... <hline> and <center> especially the code for hline is cryptic, but the idea is that it fills the line to the width of the terminal */ if (!cstrnicmp(code, "<hline>", 7)) { int l; code += 7; if (!*code) return 6; c = ((usr->display->term_width-1) > PRINT_BUF) ? PRINT_BUF : (usr->display->term_width-1); cstrncpy(buf, code, c); /* it stinks, but you have to remove all chars that can reset the cursor pos */ p = buf; while(*p) { if (*p == KEY_CTRL('X') || *p == '\b') memmove(p, p+1, strlen(p+1)+1); else { if (*p == '\n') { /* don't go over newlines */ *p = 0; break; } p++; } } l = strlen(buf); i = color_strlen(buf); while(*cpos + i < usr->display->term_width-1) Out_text(dev, usr, buf, cpos, lines, max_lines, AUTO_COLOR_FORCED); /* recurse */ if (*cpos + i >= usr->display->term_width-1) { /* 'partial put' of the remainder */ buf[color_index(buf, c - *cpos)] = 0; Out_text(dev, usr, buf, cpos, lines, max_lines, AUTO_COLOR_FORCED); } return 6+l; } if (!cstrnicmp(code, "<center>", 8)) { code += 8; if (!*code) return 7; c = strlen(code); c = (c > PRINT_BUF) ? PRINT_BUF : c; cstrncpy(buf, code, c); buf[c-1] = 0; if ((p = cstrchr(buf, '\n')) != NULL) /* don't go over newlines */ *p = 0; i = (usr->display->term_width-1)/2 - color_strlen(buf)/2 - *cpos; while(i > 0) { write_StringIO(dev, " ", 1); (*cpos)++; i--; } return 7; } if ((usr->flags & USR_ANSI) && !(usr->flags & USR_DONT_AUTO_COLOR) && !dont_auto_color) { auto_color(usr, colorbuf, MAX_COLORBUF); put_StringIO(dev, colorbuf); } write_StringIO(dev, "<", 1); (*cpos)++; if ((usr->flags & USR_ANSI) && !(usr->flags & USR_DONT_AUTO_COLOR) && !dont_auto_color) { restore_colorbuf(usr, usr->color, colorbuf, MAX_COLORBUF); put_StringIO(dev, colorbuf); } return 0; }
/* load all rooms definitions at startup Note that room #1 and room #2 are 'shadow' rooms for Mail> and Home> the BBS cannot work without room #0, #1, and #2 */ int init_Room(void) { char buf[MAX_PATHLEN], *bufp; DIR *dirp; struct dirent *direntp; struct stat statbuf; Room *newroom; unsigned int u; int load_room_flags, len; printf("\n"); listdestroy_Room(AllRooms); AllRooms = Lobby_room = NULL; load_room_flags = LOAD_ROOM_ALL; if (!PARAM_HAVE_RESIDENT_INFO) load_room_flags &= ~LOAD_ROOM_INFO; bufprintf(buf, sizeof(buf), "%s/", PARAM_ROOMDIR); path_strip(buf); len = strlen(buf); bufp = buf+len; if ((dirp = opendir(buf)) == NULL) return -1; while((direntp = readdir(dirp)) != NULL) { if (is_numeric(direntp->d_name)) { /* only do numeric directories */ cstrcpy(bufp, direntp->d_name, MAX_PATHLEN - len); if (stat(buf, &statbuf)) continue; if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { u = (unsigned int)cstrtoul(bufp, 10); printf("loading room %3u ... ", u); fflush(stdout); if ((newroom = load_Room(u, load_room_flags)) != NULL) { (void)prepend_Room(&AllRooms, newroom); room_readdir(newroom); printf("%s>\n", newroom->name); } else { printf("FAILED!\n"); closedir(dirp); listdestroy_Room(AllRooms); AllRooms = Lobby_room = NULL; return -1; } } } } closedir(dirp); if (PARAM_HAVE_CATEGORY) (void)sort_Room(&AllRooms, room_sort_by_category); else (void)sort_Room(&AllRooms, room_sort_by_number); /* find the Lobby> It should be first, but you never know... */ if (Lobby_room == NULL) { Room *rm; for(rm = AllRooms; rm != NULL; rm = rm->next) { if (!rm->number) { Lobby_room = rm; break; } } } if (Lobby_room == NULL) { printf("Failed to find the Lobby> (room 0)\n" "Please create room definition file '%s/0/RoomData'\n", PARAM_ROOMDIR); listdestroy_Room(AllRooms); AllRooms = NULL; return -1; } printf("\n"); return 0; }