/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Dystopia Mud improvements copyright (C) 2000, 2001 by Brian Graversen * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*************************************************************************** * _/ _/ * * _/_/_/ _/_/ _/_/_/ _/ _/_/ _/ _/ _/_/_/ * * _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ * * _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ * * _/ _/ _/ _/_/_/ _/ _/_/ _/_/_/ _/_/_/ * *************************************************************************** * Mindcloud Copyright 2001-2003 by Jeff Boschee (Zarius), * * Additional credits are in the help file CODECREDITS * * All Rights Reserved. * ***************************************************************************/ #if defined(macintosh) #include <types.h> #else #include <sys/types.h> #endif #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" PROJECT_DATA *get_project_by_number args((int pnum)); NOTE_DATA *get_log_by_number args((PROJECT_DATA * pproject, int pnum)); PROJECT_DATA *first_project; PROJECT_DATA *last_project; PROJECT_DATA *read_project args((FILE * fp)); void note_attach args((CHAR_DATA * ch)); void write_projects args((void)); void delete_project args((PROJECT_DATA * proj)); void load_projects(void) { FILE *fp; PROJECT_DATA *proj; first_project = NULL; last_project = NULL; if ((fp = fopen(PROJECTS_FILE, "r")) == NULL) return; while ((proj = read_project(fp))) { LINK(proj, first_project, last_project, next, prev); } return; } NOTE_DATA *read_log(FILE * fp) { NOTE_DATA *plog; char *word; plog = alloc_mem(sizeof(NOTE_DATA)); for (;;) { word = fread_word(fp); if (!str_cmp(word, "Sender")) plog->sender = fread_string(fp); else if (!str_cmp(word, "Date")) plog->date = fread_string(fp); else if (!str_cmp(word, "Subject")) plog->subject = fread_string(fp); else if (!str_cmp(word, "Text")) plog->text = fread_string(fp); else if (!str_cmp(word, "Endlog")) { fread_to_eol(fp); plog->next = NULL; return plog; } else { free_mem(plog, sizeof(NOTE_DATA)); bug("read_log: bad key word.", 0); return NULL; } } } #if defined(KEY) #undef KEY #endif #define KEY( literal, field, value ) if ( !str_cmp( word, literal ) ){field = value;fMatch = TRUE;break;} PROJECT_DATA *read_project(FILE * fp) { PROJECT_DATA *project; NOTE_DATA *plog, *tlog; char *word; char buf[MSL]; bool fMatch; char letter; do { letter = getc(fp); if (feof(fp)) { fclose(fp); return NULL; } } while (isspace(letter)) ; ungetc(letter, fp); project = alloc_mem(sizeof(PROJECT_DATA)); project->first_log = NULL; project->next = NULL; project->coder = NULL; project->description = str_dup(""); project->name = str_dup(""); project->owner = str_dup(""); project->date = str_dup("Not Set?!"); project->status = str_dup("No update."); for (;;) { word = feof(fp) ? "End" : fread_word(fp); fMatch = FALSE; switch (UPPER(word[0])) { case '*': fMatch = TRUE; fread_to_eol(fp); break; case 'C': KEY("Coder", project->coder, fread_string(fp)); break; case 'D': if (!str_cmp(word, "Date")) free_string(project->date); else if (!str_cmp(word, "Description")) free_string(project->description); KEY("Date", project->date, fread_string(fp)); KEY("Description", project->description, fread_string(fp)); break; case 'E': if (!str_cmp(word, "End")) { if (!project->description) project->description = str_dup(""); if (!project->name) project->name = str_dup(""); if (!project->owner) project->owner = str_dup(""); if (!project->date) project->date = str_dup("Not Set?!"); if (!project->status) project->status = str_dup("No update."); if (str_cmp(project->owner, "None")) project->taken = TRUE; return project; } break; case 'L': if (!str_cmp(word, "Log")) { fread_to_eol(fp); plog = read_log(fp); if (!plog) { xprintf_2(buf, "read_project: couldn't read log,aborting"); bug(buf, 0); exit(1); } if (!plog->sender) plog->sender = str_dup(""); if (!plog->date) plog->date = str_dup(""); if (!plog->subject) plog->subject = str_dup("None"); plog->to_list = str_dup(""); if (!project->first_log) project->first_log = plog; else { plog->next = project->first_log; project->first_log = plog; } fMatch = TRUE; break; } break; case 'N': KEY("Name", project->name, fread_string(fp)); break; case 'O': KEY("Owner", project->owner, fread_string(fp)); break; case 'S': KEY("Status", project->status, fread_string(fp)); break; } if (!fMatch) { xprintf(buf, "read_project: no match: %s", word); bug(buf, 0); } } for (plog = project->first_log; plog; plog = tlog) { tlog = plog->next; free_string(plog->text); free_string(plog->subject); free_string(plog->to_list); free_string(plog->date); free_string(plog->sender); plog->next = note_free; note_free = plog; } project->first_log = NULL; if (project->coder) free_string(project->coder); if (project->description) free_string(project->description); if (project->name) free_string(project->name); if (project->owner) free_string(project->owner); if (project->date) free_string(project->date); if (project->status) free_string(project->status); free_mem(project, sizeof(PROJECT_DATA)); return project; } void do_project(CHAR_DATA * ch, char *argument) { char arg[MAX_INPUT_LENGTH]; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char buf[MSL]; int pcount; int pnum; PROJECT_DATA *pproject; if (IS_NPC(ch)) return; if (!ch->desc) { bug("do_project: no descriptor", 0); return; } argument = one_argument(argument, arg); smash_tilde(argument); if (!str_cmp(arg, "save")) { write_projects(); send_to_char("Projects saved.\n\r", ch); return; } if (!str_cmp(arg, "code")) { pcount = 0; send_to_char(" ## | Owner | Project |\n\r", ch); send_to_char ("---|-------------|----------------------|--------------------------|-----------\n\r", ch); for (pproject = first_project; pproject; pproject = pproject->next) { pcount++; if ((pproject->status && str_cmp(pproject->status, "approved")) || pproject->coder != NULL) continue; xprintf(buf, "%2d | %-11s | %-20s |\n\r", pcount, pproject->owner ? pproject->owner : "(None)", pproject->name); send_to_char(buf, ch); } return; } if (!str_cmp(arg, "more") || !str_cmp(arg, "mine")) { NOTE_DATA *plog; bool MINE = FALSE; int num_logs = 0; pcount = 0; if (!str_cmp(arg, "mine")) MINE = TRUE; send_to_char("\n\r", ch); send_to_char (" ## | Owner | Project | Coder | Status | # of Logs\n\r", ch); send_to_char ("---|-------------|----------------------|---------------|------------|----------\n\r", ch); for (pproject = first_project; pproject; pproject = pproject->next) { pcount++; if (MINE && (!pproject->owner || str_cmp(ch->name, pproject->owner)) && (!pproject->coder || str_cmp(ch->name, pproject->coder))) continue; else if (!MINE && pproject->status && !str_cmp("Done", pproject->status)) continue; num_logs = 0; for (plog = pproject->first_log; plog; plog = plog->next) num_logs++; xprintf(buf, "%2d | %-11s | %-20s | %-13s | %-10s | %3d\n\r", pcount, pproject->owner ? pproject->owner : "(None)", pproject->name, pproject->coder ? pproject->coder : "(None)", pproject->status ? pproject-> status : "(None)", num_logs); send_to_char(buf, ch); } return; } if (arg[0] == '\0' || !str_cmp(arg, "list")) { bool aflag, projects_available; aflag = FALSE; projects_available = FALSE; if (!str_cmp(argument, "available")) aflag = TRUE; send_to_char("\n\r", ch); if (!aflag) { send_to_char (" ## | Owner | Project | Date | Status\n\r", ch); send_to_char ("---|-------------|----------------------|--------------------------|-----------\n\r", ch); } else { send_to_char(" ## | Project | Date\n\r", ch); send_to_char ("---|----------------------|--------------------------\n\r", ch); } pcount = 0; for (pproject = first_project; pproject; pproject = pproject->next) { pcount++; if (pproject->status && !str_cmp("Done", pproject->status)) continue; if (!aflag) xprintf(buf, "%2d | %-11s | %-20s | %-24s | %-10s\n\r", pcount, pproject->owner ? pproject-> owner : "(None)", pproject->name, pproject->date, pproject->status ? pproject-> status : "(None)"); else if (!pproject->taken) { if (!projects_available) projects_available = TRUE; xprintf(buf, "%2d | %-20s | %s\n\r", pcount, pproject->name, pproject->date); } send_to_char(buf, ch); } if (pcount == 0) send_to_char("No projects exist.\n\r", ch); else if (aflag && !projects_available) send_to_char("No projects available.\n\r", ch); return; } if (!str_cmp(arg, "add")) { char *strtime; PROJECT_DATA *new_project; /* Just to be safe */ if (get_trust(ch) < LEVEL_JUDGE) { send_to_char ("You are not powerfull enough to add a new project.\n\r", ch); return; } new_project = alloc_mem(sizeof(PROJECT_DATA)); LINK(new_project, first_project, last_project, next, prev); new_project->name = str_dup(argument); new_project->coder = NULL; new_project->taken = FALSE; new_project->owner = NULL; new_project->status = NULL; new_project->description = str_dup(""); new_project->first_log = NULL; new_project->last_log = NULL; strtime = ctime(¤t_time); strtime[strlen(strtime) - 1] = '\0'; new_project->date = str_dup(strtime); write_projects(); send_to_char("Ok.\n\r", ch); return; } if (!is_number(arg)) { send_to_char("Invalid project.\n\r", ch); return; } pnum = atoi(arg); pproject = get_project_by_number(pnum); if (!pproject) { send_to_char("No such project.\n\r", ch); return; } argument = one_argument(argument, arg1); if (!str_cmp(arg1, "desc")) { if (pproject->description == NULL) pproject->description = str_dup(""); string_append(ch, &pproject->description); return; } if (!str_cmp(arg1, "delete")) { NOTE_DATA *plog, *tlog; if (get_trust(ch) < LEVEL_HIGHJUDGE) { send_to_char ("You are not high enough level to delete a project.\n\r", ch); return; } tlog = NULL; for (plog = pproject->first_log; plog; tlog = plog, plog = plog->next) { if (tlog == NULL) pproject->first_log = plog->next; else tlog->next = plog->next; free_note(plog); } pproject->last_log = NULL; UNLINK(pproject, first_project, last_project, next, prev); free_string(pproject->name); if (pproject->coder) free_string(pproject->coder); if (pproject->owner) free_string(pproject->owner); if (pproject->description) free_string(pproject->description); if (pproject->date) free_string(pproject->date); if (pproject->status) free_string(pproject->status); free_mem(pproject, sizeof(*pproject)); write_projects(); send_to_char("Ok.\n\r", ch); return; } if (!str_cmp(arg1, "take")) { if (pproject->taken && pproject->owner && !str_cmp(pproject->owner, ch->name)) { pproject->taken = FALSE; free_string(pproject->owner); pproject->owner = NULL; send_to_char("You removed yourself as the owner.\n\r", ch); write_projects(); return; } else if (pproject->taken) { send_to_char("This project is already taken.\n\r", ch); return; } if (pproject->owner) free_string(pproject->owner); pproject->owner = str_dup(ch->name); pproject->taken = TRUE; write_projects(); send_to_char("Ok.\n\r", ch); return; } if (!str_cmp(arg1, "coder")) { if (pproject->coder && !str_cmp(ch->name, pproject->coder)) { free_string(pproject->coder); pproject->coder = NULL; send_to_char("You removed yourself as the coder.\n\r", ch); write_projects(); return; } else if (pproject->coder) { send_to_char("This project already has a coder.\n\r", ch); return; } pproject->coder = str_dup(ch->name); write_projects(); send_to_char("Ok.\n\r", ch); return; } if (!str_cmp(arg1, "status")) { if (pproject->owner && str_cmp(pproject->owner, ch->name) && get_trust(ch) < LEVEL_JUDGE && pproject->coder && str_cmp(pproject->coder, ch->name)) { send_to_char("This is not your project!\n\r", ch); return; } if (pproject->status) free_string(pproject->status); pproject->status = str_dup(argument); write_projects(); send_to_char("Done.\n\r", ch); return; } if (!str_cmp(arg1, "show")) { if (pproject->description) send_to_char(pproject->description, ch); else send_to_char ("That project does not have a description.\n\r", ch); return; } if (!str_cmp(arg1, "log")) { NOTE_DATA *plog, *tlog; if (!str_cmp(argument, "write")) { string_append(ch, &ch->pnote->text); return; } argument = one_argument(argument, arg2); if (!str_cmp(arg2, "subject")) { note_attach(ch); free_string(ch->pnote->subject); ch->pnote->subject = str_dup(argument); send_to_char("Ok.\n\r", ch); return; } if (!str_cmp(arg2, "post")) { char *strtime; if (pproject->owner && str_cmp(ch->name, pproject->owner) && pproject->coder && str_cmp(ch->name, pproject->coder) && get_trust(ch) < LEVEL_JUDGE) { send_to_char("This is not your project!\n\r", ch); return; } if (!ch->pnote) { send_to_char ("You have no log in progress.\n\r", ch); return; } if (!ch->pnote->subject) { send_to_char("Your log has no subject.\n\r", ch); return; } strtime = ctime(¤t_time); strtime[strlen(strtime) - 1] = '\0'; ch->pnote->date = str_dup(strtime); ch->pnote->sender = ch->name; plog = ch->pnote; ch->pnote = NULL; if (!pproject->first_log) pproject->first_log = plog; else { for (tlog = pproject->first_log; tlog->next; tlog = tlog->next) ; tlog->next = plog; } plog->next = NULL; pproject->last_log = plog; write_projects(); send_to_char("Ok.\n\r", ch); return; } if (!str_cmp(arg2, "list")) { if (pproject->owner && pproject->coder && str_cmp(ch->name, pproject->owner) && get_trust(ch) < LEVEL_BUILDER && str_cmp(ch->name, pproject->coder)) { send_to_char("This is not your project!\n\r", ch); return; } pcount = 0; xprintf(buf, "Project: %-12s: %s\n\r", pproject->owner ? pproject->owner : "(None)", pproject->name); send_to_char(buf, ch); for (plog = pproject->first_log; plog; plog = plog->next) { pcount++; xprintf(buf, "%2d) %-12s: %s\n\r", pcount, plog->sender, plog->subject); send_to_char(buf, ch); } if (pcount == 0) send_to_char("No logs available.\n\r", ch); return; } if (!is_number(arg2)) { send_to_char("Invalid log.\n\r", ch); return; } pnum = atoi(arg2); plog = get_log_by_number(pproject, pnum); if (!plog) { send_to_char("Invalid log.\n\r", ch); return; } if (!str_cmp(argument, "delete")) { if (pproject->owner && str_cmp(ch->name, pproject->owner) && get_trust(ch) < LEVEL_JUDGE && pproject->coder && str_cmp(ch->name, pproject->coder)) { send_to_char("This is not your project!\n\r", ch); return; } for (tlog = pproject->first_log; tlog->next; tlog = tlog->next) if (tlog->next == plog) break; tlog->next = plog->next; free_note(plog); write_projects(); send_to_char("Ok.\n\r", ch); return; } if (!str_cmp(argument, "read")) { if (pproject->owner && pproject->coder && str_cmp(ch->name, pproject->owner) && get_trust(ch) < LEVEL_BUILDER && str_cmp(ch->name, pproject->coder)) { send_to_char("This is not your project!\n\r", ch); return; } xprintf(buf, "[%3d] %s: %s\n\r%s\n\r%s", pnum, plog->sender, plog->subject, plog->date, plog->text); send_to_char(buf, ch); return; } } send_to_char("Unknown syntax see help 'PROJECT'.\n\r", ch); return; } PROJECT_DATA *get_project_by_number(int pnum) { int pcount; PROJECT_DATA *pproject; pcount = 0; for (pproject = first_project; pproject; pproject = pproject->next) { pcount++; if (pcount == pnum) return pproject; } return NULL; } NOTE_DATA *get_log_by_number(PROJECT_DATA * pproject, int pnum) { int pcount; NOTE_DATA *plog; pcount = 0; for (plog = pproject->first_log; plog; plog = plog->next) { pcount++; if (pcount == pnum) return plog; } return NULL; } void note_attach(ch) CHAR_DATA *ch; { NOTE_DATA *pnote; if (ch->pnote != NULL) return; if (note_free == NULL) { pnote = alloc_perm(sizeof(*ch->pnote)); } else { pnote = note_free; note_free = note_free->next; } pnote->next = NULL; pnote->sender = str_dup(ch->name); pnote->date = str_dup(""); pnote->to_list = str_dup(""); pnote->subject = str_dup(""); pnote->text = str_dup(""); ch->pnote = pnote; return; } void write_projects() { PROJECT_DATA *project; NOTE_DATA *plog; FILE *fpout; fpout = fopen(PROJECTS_FILE, "w"); if (!fpout) { bug("FATAL: cannot open projects.txt for writing!\n\r", 0); return; } for (project = first_project; project; project = project->next) { fprintf(fpout, "Name %s~\n", project->name); fprintf(fpout, "Owner %s~\n", (project->owner) ? project->owner : "None"); if (project->coder) fprintf(fpout, "Coder %s~\n", project->coder); fprintf(fpout, "Status %s~\n", (project->status) ? project->status : "No update."); fprintf(fpout, "Date %s~\n", (project->date) ? project->date : "Not Set?!?"); if (project->description) fprintf(fpout, "Description %s~\n", strip_cr(project->description)); if (project->first_log) for (plog = project->first_log; plog; plog = plog->next) fprintf(fpout, "Log\n" "Sender %s~\n" "Date %s~\n" "Subject %s~\n" "Text %s~\n" "Endlog\n", plog->sender, plog->date, plog->subject, plog->text); fprintf(fpout, "End\n"); } fclose(fpout); }