cdirt/ascii/
cdirt/data/BULL/
cdirt/data/ZONES/PENDING/
cdirt/pending/
cdirt/src/utils/
cdirt/utils/
/* prometheus's new editor */
#include <stdlib.h>

#include "edit.h"
#include "sflags.h"
#include "pflags.h"

/* This is the command to edit files in the data directory */

void editcom() {
  char path[256];

  if (!ptstflg(mynum, PFL_EDITOR))
    bprintf("You can't use the editor!\n");
  else {
    if(brkword() != 1 && wordbuf != NULL && wordbuf[0] != '\0') {
      sprintf(path, "%s/%s", EDIT_PATH, wordbuf);
      start_editor("You may use game commands with *command.",
		   "&+W[&+BC-Edit %.3d&+W] &N",
		   path, path, False, TYPE_WRITE);
    }
    else
      bprintf("Edit what?\n"); 
  }
}

/* This is the command to start the editor.
 * message...... displayed on startup
 * prompt....... a prompt with %d somewhere in it for the line number
 * infile....... file to load, NULL if none
 * outfile...... output file to write to
 * quote........ should a ">" be placed on each line of infile?
 * type......... type of output file, one of:
 * TYPE_MAIL, TYPE_APPEND, TYPE_CREATE, TYPE_DESC, TYPE_WRITE */

void start_editor(char *message,
		  char *prompt, 
		  char *infile,  
		  char *outfile,
		  Boolean quote,
		  int type){

  cur_player->edit_inp_handler = phandler(mynum);
  bprintf(E_TITLE);
  bprintf("%s\n", message);
  strcpy(eprompt, prompt);
  edit_status = NORMAL_MODE;
  cur_player->edit_mode = type;
  strcpy(cur_player->edit_outfile, outfile);
  curr_line = 1;
  if (infile != NULL) {
    load_buff(infile, quote);
    if (type == TYPE_MAIL || type == TYPE_DESC)
      view_text();
  }
  show_prompt();
  replace_input_handler(edit1);
}

void queue_line(int linenum) {
  for (txt_curr = txt_start; linenum > 0 && txt_curr->next != NULL;
       txt_curr = txt_curr->next, linenum--);
}

/* should be switched over to unix IO */
void load_buff(char *infile, Boolean quote) {
  FILE *fptr;
  char buff[MAX_COM_LEN];
 
  numlines = 0;
  txt_curr = txt_start = NULL;

  if ((fptr = FOPEN(infile, "r")) == NULL)
    return;
  else {
    if (quote)
      while (1) {
	fgets(&buff[2], MAX_COM_LEN - 3, fptr);
	if (feof(fptr))
	  break;
	else {
	  buff[0] = '>';
	  buff[1] = ' ';
	  new_line(buff);
	}
      }
    else
      while (1) {
	fgets(buff, MAX_COM_LEN - 1, fptr);
	if (feof(fptr))
	  break;
	else
	  new_line(buff);
      }
    FCLOSE(fptr);
    if (quote)
      bprintf(QUOTE_MSG, numlines);
    else if (cur_player->edit_mode == TYPE_DESC)
      bprintf(DESC_MSG, numlines);
    else if (plev(mynum) < LVL_DEMI) {
      if (numlines)
	bprintf(READ_MSG, numlines, (numlines > 1) ? "s" : "");
      else
	bprintf(READ_MSG2);
    }
    else
      bprintf(GOD_READ_MSG, numlines, (numlines > 1) ? "s" : "", infile);
  }
}

void save_buff(char *outfile, int type) {
  int fd;
  int open_flags = 0;
  Text_Ptr txt_ptr;

  if (numlines)
    bprintf(SAVE_MSG, numlines, (numlines > 1) ? "s" : "" );
  else
    bprintf(SAVE_MSG2);
  
  switch (type) {
  case TYPE_APPEND:
    open_flags = O_WRONLY | O_APPEND | O_CREAT;
    break;
  case TYPE_CREATE: case TYPE_MAIL: case TYPE_DESC:
    open_flags = O_WRONLY | O_CREAT | O_TRUNC;
    break;
  case TYPE_WRITE:
    open_flags = O_WRONLY | O_CREAT;
    break;
  }
  if ((fd = OPEN(outfile, open_flags, 0664)) != -1)
    {
      if (type == TYPE_MAIL)
	store_header(fd);

      for (txt_ptr = txt_start; txt_ptr != NULL; txt_ptr = txt_ptr->next)
	write(fd, txt_ptr->line, strlen(txt_ptr->line));
      if (type == TYPE_MAIL)
	write(fd, "***\n", 4);
      CLOSE(fd);
    }
  else {
    bprintf("Error saving file.\n");
    mudlog("ERROR: save_buff");
  }
}

void free_list() {
  Text_Ptr txt_ptr;
  Text_Ptr tmpptr = NULL;
  
  for (txt_ptr = txt_start; txt_ptr != NULL; txt_ptr = txt_ptr->next) {
    FREE(tmpptr);
    tmpptr = txt_ptr;
  }
  FREE(tmpptr);
  txt_curr = txt_start = NULL;
  numlines = 0;
  curr_line = 1;
}

void new_line(char *input) {
  Text_Ptr newline;
  int j;
  Boolean newline_found = False;

  newline = NEW(Text_Line, 1);

  for (j = 0 ; input[j] != '\0' ; j++) {
    newline->line[j] = input[j];
    if (input[j] == '\n')
      newline_found = True;
  }

  if (newline_found)                          /* restore null */
    newline->line[j] = '\0';
  else {
    newline->line[j] = '\n';
    newline->line[j + 1] = '\0';
  }

  newline->next = NULL;
  if (numlines == 0)                           /* first line of text */
    txt_start = txt_curr = newline;
  else {
    txt_curr->next = newline;
    txt_curr = txt_curr->next;
  }
  numlines++;
  curr_line++;
}

void add_lines(int linenum) {
  if (linenum > 0) {
    bprintf(ADD_MSG, linenum);
    linenum--;
  }
  else
    bprintf(ADD_MSG2);

  queue_line(linenum);
  if (txt_curr != NULL)
    cur_player->tmp_ptr = txt_curr->next;
  else
    cur_player->tmp_ptr = NULL;
  edit_status = ADD_MODE;
  edit1(NULL);
}

void delete_line(int linenum) {
  Text_Ptr tmpptr;

  if ((linenum - 1) == 0) {
    tmpptr = txt_start;
    txt_start = txt_start->next;
    FREE(tmpptr);
  }
  else {
    queue_line(linenum - 2);
    tmpptr = txt_curr->next;
    txt_curr->next = txt_curr->next->next;
    FREE(tmpptr);
  }
  numlines--;
}

void view_text (void) {
  int j = 1;
  Text_Ptr txt_ptr;

  bprintf( "\n" );
  for (txt_ptr = txt_start ; txt_ptr != NULL ; txt_ptr = txt_ptr->next)
    bprintf("&+B[&+M%.3d&+B]&+W: %s", j++, txt_ptr->line);
  bprintf("\n");
}

/* return difference of 2 input numbers */
int getnum (char *str, int *num) {
  char *ptr;
  int num1, num2;

    for (ptr = str ; !isdigit(*ptr) ; ptr++) {
      if (*ptr == '\0') {
	bprintf("This command must be followed by a number.\n");
        return -1;
      }
    }
    num1 = atoi(ptr); 
    if ((ptr = strchr(str, '-')) != NULL) {
      if (num1 == 0 || (num2 = atoi(ptr + 1)) == 0) {
	bprintf("To use this feature, type a range.  Ex: D 1-5\n");
	return -1;
      }
      else {
	if (num1 > numlines || num2 > numlines || 
	    num1 < 1 || num2 < 1 ||
	    ((num2 - num1) < 0)) {
	  bprintf("Number out of range.\n");
	  return -1;
	}
	else {
	*num = num1;
	return(num2 - num1 + 1);
	}
      }
    }
    else {
    *num = num1;
    if (*num > numlines || *num < 1) {
      bprintf("Number out of range.\n");
      return -1;
    }
    else
      return 1;
  }
}

void show_prompt() {
  static char edit_prompt[80];
  sprintf(edit_prompt, eprompt, curr_line);
  strcpy(cur_player->cprompt, edit_prompt);
}

void editor_help(void) {
  bprintf("\nHelp for the &+BCDirt editor commands:\n\n"
          "&+RE&+WX&+Rit&N................... Save the buffer, then exit\n"
          "&+WS&+Mave&N................... Save the buffer\n"
          "&+WC&+Yancel&N................. Stop editing this buffer\n"
	  "&+WNew&N.................... Start editing from srcatch\n"
          "&+WD&+Celete [Line#]&N.. ...... *Delete a line of text\n"
          "&+WD&+Belete [Line# - Line#].&N *Delete multiple lines of text\n"
          "&+WI&+Gnsert [Line#]&N......... *Insert text after [line #]\n"
	  "&+W*&+y[command]&N............. Run a mud command in editor\n"
	  "&+W=&+y[command&N.............. Run a menu command from edit mode\n"
          "&+y[return]&N............... View current buffer\n\n"
          "&+Y*Note: Commands marked with an asterisk will cause lines to be "
	  "re-numbered\n&+YAs this may cause some confusion, it is probably "
	  "best to issue the command,\nthen type &+y[RETURN]&+Y to view the "
	  "buffer.\n");
}

void clean_up() {
  if (cur_player->inmailer) {
    strcpy(cur_player->cprompt, MAILPROMPT);
    bprintf(RETURN_MSG);
  }
  else
    strcpy(cur_player->cprompt, (char *) build_prompt(mynum));
  replace_input_handler(cur_player->edit_inp_handler);
}

/* not working yet */
int cancel_buff(char *input) {
  if (input == NULL) {
    bprintf(CANCEL_MSG);
    replace_input_handler( (void *) cancel_buff);
  }
  else if (*input == 'Y' || *input == 'y') {
    bprintf(CANCELED);
  }
  else if (*input == 'N' || *input == 'n') {
    bprintf("Cancel aborted.\n");
    edit1(NULL);
    return 0;
  }
  else
    replace_input_handler((void *) cancel_buff);
  return 0;
}

void send_mail() {
  int sendto, tmp_mynum, fd1, fd2;
  char tmp_path[256];
  char mail_path[256];
  char buff[MAX_COM_LEN];
  PERSONA p;
  int numread;

    /* copy tmp file to player's mailbox */

    /* Internet email */
#ifdef INTERNET_EMAIL
    if( is_internet_email( cur_player->work_msg->mailto ) ) {
      char sendmail[200];
      char title[TITLE_LEN];
      char type = 'w';
      FILE *fptr;

      strip_color( title, make_title( ptitle(mynum), pname(mynum) ) );

      sprintf( sendmail, "%s -f%s -F \"%s\" -odb %s", SENDMAIL,
                         pname(mynum),
			 title,
                         cur_player->work_msg->mailto);
      fptr = popen( sendmail, &type );

      if( !fptr ) {
        bprintf( "Odd, couldn't send the mail.  Sorry.\n" );
        return;
      }

      fprintf( fptr, 
	   "Organization: &$ (&H: &P)\n"
           "X-Mailer: CDirt Mud Mailer (C) Weinerdog and Mancini.\n");

      strcpy(tmp_path, cur_player->edit_outfile);

      if((fd1 = OPEN(tmp_path, O_RDONLY, 0644)) != -1) {
        while ((numread = read(fd1, buff, MAX_COM_LEN)) > 0)
          fwrite( buff, numread, 1, fptr );
        CLOSE(fd1);
      }
      else {
        bprintf( "Couldn't open temp file\n" );
        return;
      }

      fputs( ".", fptr );
      pclose( fptr );
      bprintf( "Internet e-mail sent!\n" ); 
      return;
    }
#endif /* INTERNET_EMAIL */

  strcpy(tmp_path, cur_player->edit_outfile);
  sprintf(mail_path, "%s/%s", MAILDIR, cur_player->work_msg->mailto);

  if (((fd1 = OPEN(tmp_path, O_RDONLY, 0644)) != -1) &&
      ((fd2 = OPEN(mail_path, O_WRONLY | O_APPEND | O_CREAT, 0664)) != -1)) {
    while ((numread = read(fd1, buff, MAX_COM_LEN)) > 0)
      write (fd2, buff, numread);
    CLOSE(fd1);
    CLOSE(fd2);

  /* send received-mail message & update list */

    sendto = fpbn(cur_player->work_msg->mailto);
    if (sendto != -1) {
      if(players[sendto].inmailer) {
	tmp_mynum = real_mynum;
	setup_globals(sendto);
	loadmail();
	listmail();
	setup_globals(tmp_mynum);
      }
      ssetflg(sendto, SFL_MAIL);
      sendf(sendto,"&+Y***&+W\a You have received new mail from %s &+Y***\n",
	    pname(mynum));
    }
    else {
      if( getuaf( cur_player->work_msg->mailto, &p ) )
	set_bit( &p.ublock.psflags, SFL_MAIL );
      putuaf(&p);
    }
  }
  else { 
    bprintf("Error saving file.\n");
    mudlog("ERROR: send_mail\n");
  }
}

void edit1(char *input) {
  int num, count;

  if (input == NULL)
    show_prompt();
  else if (edit_status != MENU_MODE && input[0] != '=') { 
    if (input[0] == '*') {
      if (input[1] == '*') {                                 /* "**" == exit */
	if (edit_status == ADD_MODE) {    /* adding something in? ifso, link */
	  if (cur_player->tmp_ptr != NULL)        /* have something typed in */
	    txt_curr->next = cur_player->tmp_ptr;
	  else
	    txt_curr = NULL;
	}
	if (cur_player->edit_mode == TYPE_MAIL)
	  strcpy(cur_player->cprompt, MAIL_PROMPT);
	else if (cur_player->edit_mode == TYPE_DESC)
	  strcpy(cur_player->cprompt, DESC_PROMPT);
	else
	  strcpy(cur_player->cprompt, EDIT_PROMPT);
	edit_status = MENU_MODE;
      }
      else {                             /* game command */
	replace_input_handler(cur_player->edit_inp_handler);
	gamecom(input+1, True);
	edit1(NULL);
      }
    }
    else {                             /* normal case: add this line of text */
      new_line(input);
      show_prompt();
    }
  }
  else if (edit_status == MENU_MODE || input[0] == '=') {  
                                      /* MENU MODE or =command */
    switch ((input[0] == '=') ? tolower(input[1]) : tolower(input[0])) {
    case 'c':                         /* cancel */
      if (cur_player->edit_mode == TYPE_MAIL)
	bprintf("Message cancelled.\n");
      else
	bprintf("Buffer &+Ynot &Nsaved.\n");
      free_list();
      clean_up();
      return;
    case 'e': case 'x': case 'q':                            /* save/exit */
      save_buff(cur_player->edit_outfile, cur_player->edit_mode);
      if (cur_player->edit_mode == TYPE_MAIL)
	send_mail();
      free_list();
      clean_up();
      return;
    case 'd':                         /* delete a line */
      if ((count = getnum(input, &num)) != -1) {
	if (count == 1)
	  bprintf("[Line %d deleted]\n", num);
	else
	  bprintf("[Lines %d through %d deleted]\n", num, num + count - 1);
	while (count-- > 0)
	  delete_line(num);
      }
      break;
    case 'i':                         /* add a line */
      if ((getnum(input, &num)) != -1) {
	curr_line = num + 1;
	add_lines(num);
      }
      break;
    case '?': case 'h':               /* help        */
      editor_help();
      break;
    case 'n':                         /* new buffer  */
      free_list();
      add_lines(0);
      break;
    case 's':                         /* save buffer */
      save_buff(cur_player->edit_outfile, cur_player->edit_mode);
      break;
    case '\0': case 'v':              /* view buffer */
      view_text();
      break;
    default:
      bprintf("Command Invalid; Type ? for help.\n");
      break;
    }
    if (edit_status == MENU_MODE)
      bprintf(EDIT_PROMPT);
    else if (input[0] == '=' && input[1] != 'n' && input[1] != 'i')
      show_prompt();
  }
  replace_input_handler(edit1);
}