/* * macro.c - ported from BattleTech 3056 MUSE */ /* * $Id: macro.c,v 1.3 2005/08/08 09:43:07 murrayma Exp $ */ #include "copyright.h" #include "config.h" #include "macro.h" #include "commac.h" #include "config.h" #include "flags.h" #include "powers.h" #include "db.h" #include "alloc.h" extern dbref match_thing(dbref player, char *name); MACENT macro_table[] = { {(char *) "add", do_add_macro}, {(char *) "clear", do_clear_macro}, {(char *) "chmod", do_chmod_macro}, {(char *) "chown", do_chown_macro}, {(char *) "create", do_create_macro}, {(char *) "def", do_def_macro}, {(char *) "del", do_del_macro}, {(char *) "name", do_desc_macro}, {(char *) "chslot", do_edit_macro}, {(char *) "ex", do_ex_macro}, {(char *) "gex", do_gex_macro}, {(char *) "glist", do_list_macro}, {(char *) "list", do_status_macro}, {(char *) "undef", do_undef_macro}, {(char *) NULL, NULL} }; void init_mactab(void) { MACENT *mp; hashinit(&mudstate.macro_htab, 5 * HASH_FACTOR); for (mp = macro_table; mp->cmdname; mp++) hashadd(mp->cmdname, (int *) mp, &mudstate.macro_htab); } int do_macro(player, in, out) dbref player; char *in, **out; { char *s; char *cmd; MACENT *mp; char *old; cmd = in + 1; if (!isPlayer(player)) { notify(player, "MACRO: Only players may use macros."); return 0; } old = alloc_lbuf("do_macro"); StringCopy(old, in); for (s = cmd; *s && *s != ' '; s++); if (*s == ' ') *s++ = 0; mp = (MACENT *) hashfind(cmd, &mudstate.macro_htab); if (mp != NULL) { (*(mp->handler)) (player, s); free_lbuf(old); return 0; } if ((*out = do_process_macro(player, in, s)) != NULL) { free_lbuf(old); return 1; } else { StringCopy(in, old); free_lbuf(old); return 2; /* * return any value > 1, and command * * * * processing will */ } /* * continue */ } void do_list_macro(player, s) dbref player; char *s; { int i; int notified = 0; struct macros *m; char *unparse; for (i = 0; i < nummacros; i++) { m = macros[i]; if (can_read_macros(player, m)) { if (!notified) { notify(player, "Num Description Owner LRW"); notified = 1; } unparse = unparse_object(player, m->player, 0); notify(player, tprintf("%-4d %-35.35s %-24.24s %c%c%c", i, m->desc, unparse, m->status & MACRO_L ? 'L' : '-', m->status & MACRO_R ? 'R' : '-', m->status & MACRO_W ? 'W' : '-')); free_lbuf(unparse); } } if (!notified) notify(player, "MACRO: There are no macro sets you can read."); } void do_add_macro(player, s) dbref player; char *s; { int first; int set; struct macros *m; struct commac *c; int i; c = get_commac(player); first = -1; for (i = 0; i < 5 && first < 0; i++) if (c->macros[i] == -1) first = i; if (first < 0) { notify(player, "MACRO: Sorry, you already have 5 sets defined on you."); } else if (is_number(s)) { set = atoi(s); if (set >= 0 && set < nummacros) { m = macros[set]; if (can_read_macros(player, m)) { c->macros[first] = set; notify(player, tprintf("MACRO: Macro set %d added in the %d slot.", set, first)); } else { notify(player, "MACRO: Permission denied."); } } else { notify(player, "MACRO: That macro set does not exist."); return; } } else { notify(player, "MACRO: What set do you want to add to your macro system?"); } } void do_del_macro(player, s) dbref player; char *s; { struct commac *c; int set; c = get_commac(player); if (is_number(s)) { set = atoi(s); if (set >= 0 && set < 5 && c->macros[set] >= 0) { c->macros[set] = -1; notify(player, tprintf("MACRO: Macro slot %d cleared.", set)); if (set == c->curmac) { c->curmac = -1; notify(player, "MACRO: Deleted current slot, resetting to none."); } } else notify(player, "MACRO: That is not a legal macro slot."); } else notify(player, "MACRO: What set did you want to delete from your macro system?"); } void do_desc_macro(player, s) dbref player; char *s; { struct macros *m; m = get_macro_set(player, -1); if (m) { free(m->desc); m->desc = (char *) malloc(strlen(s) + 1); StringCopy(m->desc, s); notify(player, tprintf("MACRO: Current slot description to %s.", s)); } else notify(player, "MACRO: You have no current slot set."); } void do_chmod_macro(player, s) dbref player; char *s; { struct macros *m; int sign; m = get_macro_set(player, -1); if (m) { if ((m->player != player) && !Wizard(player)) { notify(player, "MACRO: Permission denied."); return; } if (*s == '!') { sign = 0; s++; } else sign = 1; switch (*s) { case 'L': case 'l': if (sign) { m->status |= MACRO_L; notify(player, "MACRO: Default Macro Slot is now locked and unwritable."); } else { m->status &= ~MACRO_L; notify(player, "MACRO: Default Macro Slot is now unlocked."); } break; case 'R': case 'r': if (sign) { m->status |= MACRO_R; notify(player, "MACRO: Default Macro Slot set to be readable by others"); } else { m->status &= ~MACRO_R; notify(player, "MACRO: Default Macro Slot set to be not readable by others"); } break; case 'W': case 'w': if (sign) { m->status |= MACRO_W; notify(player, "MACRO: Default Macro Slot set to be writable by others"); } else { m->status &= ~MACRO_W; notify(player, "MACRO: Default Macro Slot set to be not writable by others"); } break; default: notify(player, "MACRO: Sorry, unknown mode. Legal modes are: L R W"); } } else notify(player, "MACRO: You have no current slot set."); } void do_gex_macro(player, s) dbref player; char *s; { struct macros *m; int which; int i; char buffer[LBUF_SIZE]; if (!s || !*s) { notify(player, "MACRO: You need to specify a macro set."); return; } if (is_number(s)) { which = atoi(s); if ((which >= nummacros) || (which < 0) || (nummacros == 0)) { notify(player, tprintf ("MACRO: Illegal Macro Set. Macros go from 0 to %d.", nummacros - 1)); return; } else m = macros[which]; } else { notify(player, "MACRO: I do not see that set here."); return; } if (m && can_read_macros(player, m)) { notify(player, tprintf("Macro Definitions for %s", m->desc)); for (i = 0; i < m->nummacros; i++) { sprintf(buffer, " %-5.5s: %s", m->alias + i * 5, m->string[i]); notify(player, buffer); } } else notify(player, "MACRO: Permission denied."); } void do_edit_macro(player, s) dbref player; char *s; { struct commac *c; int set; c = get_commac(player); if (is_number(s)) { set = atoi(s); if (set >= 0 && set < 5 && GMac(c->macros[set])) { c->curmac = set; notify(player, tprintf("MACRO: Current slot set to %d.", set)); } else notify(player, "MACRO: That is not a legal macro slot."); } else notify(player, "MACRO: What slot did you want to make current?"); } void do_status_macro(player, s) dbref player; char *s; { int i; struct commac *c; struct macros *m; char *unparse; c = get_commac(player); notify(player, "#: Num Description Owner LRW"); for (i = 0; i < 5; i++) { if (c->macros[i] >= 0) if (!(GMac(c->macros[i]))) notify(player, tprintf("%d: INVALID MACRO SET!", i)); else { m = macros[c->macros[i]]; unparse = unparse_object(player, m->player, 0); notify(player, tprintf("%d: %-4d %-35.35s %-24.24s %c%c%c", i, c->macros[i], m->desc, unparse, m->status & MACRO_L ? 'L' : '-', m->status & MACRO_R ? 'R' : '-', m->status & MACRO_W ? 'W' : '-')); free_lbuf(unparse); } else notify(player, tprintf("%d:", i)); } notify(player, tprintf("Current Macro Slot: %d", c->curmac)); } void do_ex_macro(player, s) dbref player; char *s; { struct macros *m; int which; int i; char buffer[LBUF_SIZE]; if (is_number(s)) { which = atoi(s); m = get_macro_set(player, which); } else m = get_macro_set(player, -1); if (m) { notify(player, tprintf("Macro Definitions for %s", m->desc)); for (i = 0; i < m->nummacros; i++) { sprintf(buffer, " %-5.5s: %s", m->alias + i * 5, m->string[i]); notify(player, buffer); } } else notify(player, "MACRO: Illegal macro set to examine."); } void do_chown_macro(player, cmd) dbref player; char *cmd; { struct macros *m; dbref thing; char *unparse; m = get_macro_set(player, -1); thing = match_thing(player, cmd); if (thing == NOTHING) { notify(player, "MACRO: I do not see that here."); return; } #if 0 if (!m || !can_write_macros(player, m)) { notify(player, "MACRO: Permission denied."); } #endif if (!m) { notify(player, "MACRO: No current active macro."); return; } if (!Wizard(player)) { notify(player, "MACRO: Sorry, command limited to Wizards."); return; } m->player = thing; unparse = unparse_object(player, thing, 0); notify(player, tprintf("MACRO: Macro %s chowned to %s.", m->desc, unparse)); free_lbuf(unparse); } static void clear_macro_set(int set) { struct macros *m; struct commac *c; int i, j; if (GMac(set)) { m = macros[set]; for (i = 0; i < m->nummacros; i++) { free(m->string[i]); } free(m->alias); free(m->string); free(m); nummacros--; for (i = set; i < nummacros; i++) macros[i] = macros[i + 1]; macros[i] = NULL; } for (i = 0; i < NUM_COMMAC; i++) { c = commac_table[i]; while (c) { for (j = 0; j < 5; j++) { if (c->macros[j] == set) { c->macros[j] = -1; if (c->curmac == j) c->curmac = -1; } else if (c->macros[j] > set) { c->macros[j]--; } } c = c->next; } } } void do_clear_macro(player, s) dbref player; char *s; { int set; struct macros *m; struct commac *c; c = get_commac(player); if (c->curmac == -1) { notify(player, "MACRO: You are not currently editing a macro set."); return; } else if (c->macros[c->curmac] == -1) { notify(player, "MACRO: That is not a valid macro set."); return; } set = c->macros[c->curmac]; m = macros[set]; if (GMac(set)) { if ((player != m->player) && !Wizard(player)) { notify(player, "MACRO: You may only CLEAR your own macro sets."); return; } else if ((player == m->player) && (m->status & MACRO_L)) { notify(player, "MACRO: Sorry, that macro set is locked."); return; } } notify(player, tprintf("MACRO: Clearing macro set %d: %s.", set, GMac(set) ? m->desc : "Nonexistent")); clear_macro_set(set); } void do_def_macro(player, cmd) dbref player; char *cmd; { int i, j, where; struct macros *m; char *alias; char *s; char buffer[LBUF_SIZE]; char **ns; char *na; m = get_macro_set(player, -1); if (!m) { notify(player, "MACRO: No current set."); return; } if (!can_write_macros(player, m)) { notify(player, "MACRO: Permission denied."); return; } for (alias = cmd; *alias && *alias == ' '; alias++) *alias = 0; cmd = alias; for (; *cmd && *cmd != ' ' && *cmd != '='; cmd++); while (*cmd && *cmd == ' ') *cmd++ = '\0'; if (*cmd != '=') { notify(player, "MACRO: You must specify an = in your macro definition"); return; } *cmd++ = 0; while (*cmd && *cmd == ' ') *cmd++ = 0; s = cmd; if (!*s) { notify(player, "MACRO: You must specify a string to substitute for."); return; } else if (strlen(alias) > 4) { notify(player, "MACRO: Please limit aliases to 4 chars or less."); return; } for (j = 0; j < m->nummacros && (strcasecmp(alias, m->alias + j * 5) > 0); j++); if (j < m->nummacros && !strcasecmp(alias, m->alias + j * 5)) { notify(player, "MACRO: That alias is already defined in this set."); sprintf(buffer, "%-4.4s:%s", m->alias + j * 5, m->string[j]); notify(player, buffer); return; } if (m->nummacros >= m->maxmacros) { m->maxmacros += 10; na = (char *) malloc(5 * m->maxmacros); ns = (char **) malloc(sizeof(char *) * m->maxmacros); for (i = 0; i < m->nummacros; i++) { StringCopy(na + i * 5, m->alias + i * 5); ns[i] = m->string[i]; } free(m->alias); free(m->string); m->alias = na; m->string = ns; } where = m->nummacros++; for (i = where; i > j; i--) { StringCopy(m->alias + i * 5, m->alias + (i - 1) * 5); m->string[i] = m->string[i - 1]; } where = j; StringCopy(m->alias + where * 5, alias); m->string[where] = (char *) malloc(strlen(s) + 1); StringCopy(m->string[where], s); sprintf(buffer, "MACRO: Macro %s:%s defined.", alias, s); notify(player, buffer); } void do_undef_macro(player, cmd) dbref player; char *cmd; { int i; struct macros *m; m = get_macro_set(player, -1); if (!m || !can_write_macros(player, m)) { notify(player, "MACRO: Permission denied."); return; } for (i = 0; i < m->nummacros; i++) { if (!strcmp(m->alias + i * 5, cmd)) { free(m->string[i]); m->nummacros--; for (; i < m->nummacros; i++) { StringCopy(m->alias + i * 5, m->alias + i * 5 + 5); m->string[i] = m->string[i + 1]; } notify(player, "MACRO: Macro deleted from set."); return; } } notify(player, "MACRO: That macro is not in this set."); } char *do_process_macro(player, in, s) dbref player; char *in; char *s; { char *cmd; char *tar; char *next; struct macros *m; int first, last, current = 0; int dir; int i; struct commac *c; char *buff; c = get_commac(player); buff = alloc_lbuf("do_process_macro"); cmd = in + 1; buff[0] = '\0'; /* * End the string */ for (i = 0; i < 5; i++) { if (GMac(c->macros[i])) { m = macros[c->macros[i]]; if (m->nummacros > 0) { first = 0; last = m->nummacros - 1; dir = 1; next = in + 1; while (dir && (first <= last)) { current = (first + last) / 2; dir = strcmp(next, m->alias + 5 * current); if (dir < 0) last = current - 1; else first = current + 1; } if (!dir) { tar = m->string[current]; #if 1 /* Original MUSE code */ next = buff; while (*tar) { if (*tar == '%' && *(tar + 1) == '*') { *next++ = '*'; tar += 2; } else if (*tar == '*') { *next = 0; strcat(next, s); tar++; next += strlen(next); } else *next++ = *tar++; } *next = 0; #else while (*tar) { switch (*tar) { case '*': if (!buff) StringCopy(buff, s); else strcat(buff, s); break; case '%': if (!buff) StringCopy(buff, tar + 1); else sprintf(buff, "%s%c", buff, tar + 1); *tar++; break; default: if (!buff) StringCopy(buff, tar); else sprintf(buff, "%s%c", buff, *tar); break; } *tar++; } #endif return buff; } } } } free_lbuf(buff); return NULL; } struct macros *get_macro_set(player, which) dbref player; int which; { int set; struct commac *c; c = get_commac(player); if (c) { set = -1; if (which >= 0 && which < 5) set = c->macros[which]; else if (c->curmac >= 0) set = c->macros[c->curmac]; if (set == -1) return NULL; else return macros[set]; } else return NULL; } void do_sort_macro_set(m) struct macros *m; { int i; int cont; char buffer[10]; char *s; cont = 1; while (cont) { cont = 0; for (i = 0; i < m->nummacros - 1; i++) if (strcasecmp(m->alias + i * 5, m->alias + (i + 1) * 5) > 0) { StringCopy(buffer, m->alias + i * 5); StringCopy(m->alias + i * 5, m->alias + (i + 1) * 5); StringCopy(m->alias + (i + 1) * 5, buffer); s = m->string[i]; m->string[i] = m->string[i + 1]; m->string[i + 1] = s; cont = 1; } } } void do_create_macro(player, s) dbref player; char *s; { int first; int i; struct commac *c; struct macros **nm; int set; c = get_commac(player); first = -1; for (i = 0; i < 5 && first < 0; i++) if (c->macros[i] == -1) first = i; if (first < 0) { notify(player, "MACRO: Sorry, you already have 5 sets defined on you."); return; } if (nummacros >= maxmacros) { maxmacros += 10; nm = (struct macros **) malloc(sizeof(struct macros *) * maxmacros); for (i = 0; i < nummacros; i++) nm[i] = macros[i]; free(macros); macros = nm; } set = nummacros++; macros[set] = (struct macros *) malloc(sizeof(struct macros)); macros[set]->player = player; macros[set]->status = 0; macros[set]->nummacros = 0; macros[set]->maxmacros = 0; macros[set]->alias = NULL; macros[set]->string = NULL; macros[set]->desc = (char *) malloc(strlen(s) + 1); StringCopy(macros[set]->desc, s); c->curmac = first; c->macros[first] = set; notify(player, tprintf("MACRO: Macro set %d created with description %s.", set, s)); } int can_write_macros(player, m) dbref player; struct macros *m; { if (m->status & MACRO_L) return 0; if (m->player == player) return 1; else return m->status & MACRO_W; } int can_read_macros(player, m) dbref player; struct macros *m; { if (Wizard(player)) return 1; if (!m) return 0; if (m->player == player) return 1; else return m->status & MACRO_R; } #define TST(cmd,msg) if (cmd) { fprintf(stderr, msg); exit(1); } void load_macros(fp) FILE *fp; { int i, j; char *c; char *t; char buffer[LBUF_SIZE]; struct macros *m; TST(fscanf(fp, "%d\n", &nummacros) != 1, "Error: Loading #macros\n"); maxmacros = nummacros; if (maxmacros > 0) macros = (struct macros **) malloc(sizeof(struct macros *) * nummacros); else macros = NULL; for (i = 0; i < nummacros; i++) { macros[i] = (struct macros *) malloc(sizeof(struct macros)); m = macros[i]; fgets(buffer, LBUF_SIZE, fp); TST(sscanf(buffer, "%d %d %d\n", &(m->player), &(m->nummacros), &j) != 3, tprintf("Reading macro set #%d\n", i)); m->status = j; fgets(buffer, LBUF_SIZE, fp); if (*buffer) if (buffer[strlen(buffer) - 1] == '\n') buffer[strlen(buffer) - 1] = 0; m->desc = (char *) malloc(strlen(buffer) - 1); StringCopy(m->desc, buffer + 2); m->maxmacros = m->nummacros; if (m->nummacros > 0) { m->alias = (char *) malloc(5 * m->maxmacros); m->string = (char **) malloc(sizeof(char *) * m->nummacros); for (j = 0; j < m->nummacros; j++) { t = m->alias + j * 5; fgets(buffer, LBUF_SIZE, fp); if (buffer[strlen(buffer) - 1] == '\n') buffer[strlen(buffer) - 1] = 0; for (c = buffer; *c && *c != ' '; c++); *c = 0; if (strlen(buffer) > 4) { fprintf(stderr, "Error reading macro set #%d!\n", i); exit(1); } if (!*buffer) { /* fprintf(stderr, "Error in macro set #%d (macro %d) : Invalid macro name.\n", i, j); */ t[0] = 0; } else strcpy(t, buffer); c++; m->string[j] = (char *) malloc(strlen(c) + 1); StringCopy(m->string[j], c); } do_sort_macro_set(m); } else { m->alias = NULL; m->string = NULL; } } while (1) { for (i = 0; i < nummacros; i++) if (!isPlayer(macros[i]->player)) break; if (i >= nummacros) break; clear_macro_set(i); } } void save_macros(fp) FILE *fp; { int i, j; struct macros *m; fprintf(fp, "%d\n", nummacros); for (i = 0; i < nummacros; i++) { m = macros[i]; fprintf(fp, "%d %d %d\n", m->player, m->nummacros, (int) m->status); fprintf(fp, "D:%s\n", m->desc); for (j = 0; j < m->nummacros; j++) fprintf(fp, "%s %s\n", m->alias + j * 5, m->string[j]); } }