/* * macro.c - ported from BattleTech 3056 MUSE */ /* * $Id: macro.c,v 1.4 1995/12/03 09:18:32 root Exp root $ */ #include "copyright.h" #include "autoconf.h" #include "macro.h" #include "commac.h" #include "config.h" #include "flags.h" #include "powers.h" #include "db.h" #include "alloc.h" 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 NDECL(init_mactab) { MACENT *mp; hashinit(&mudstate.macro_htab, 15 * 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[200]; 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)); 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 && c->macros[set] >= 0) { 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) { 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[200]; 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; int i; 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 (!m || !can_write_macros(player, m)) { notify(player, "MACRO: Permission denied."); } 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); } void do_clear_macro(player, s) dbref player; char *s; { int set; struct macros *m; int i, j; 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 ((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, m->desc)); 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_def_macro(player, cmd) dbref player; char *cmd; { int i, j, where; struct macros *m; char *alias; char *s; char buffer[1000]; 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++) ; if (!*cmd) { notify(player, "MACRO: You must specify an = in your macro definition"); return; } while (*cmd && *cmd != '=') *cmd++ = 0; *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 (c->macros[i] >= 0) { 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]; 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++; } 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->player == player) return 1; else return m->status & MACRO_R; } void load_macros(fp) FILE *fp; { int i, j; char c; char *t; char buffer[1000]; struct macros *m; fscanf(fp, "%d\n", &nummacros); 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]; fscanf(fp, "%d %d %d\n", &(m->player), &(m->nummacros), &j); m->status = j; fscanf(fp, "%[^\n]\n", buffer); 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; while ((c = fgetc(fp)) != ' ') *t++ = c; *t = 0; fscanf(fp, "%[^\n]\n", buffer); m->string[j] = (char *)malloc(strlen(buffer) + 1); StringCopy(m->string[j], buffer); } do_sort_macro_set(m); } else { m->alias = NULL; m->string = NULL; } } } 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]); } }