/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | * * -----------------------------------------------------------| \\._.// * * SmaugWiz (C) 1998 by Russ Pillsbury (Windows NT version) | (0...0) * * -----------------------------------------------------------| ).:.( * * SMAUG (C) 1994, 1995, 1996 by Derek Snider | {o o} * * -----------------------------------------------------------| / ' ' \ * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, |~'~.VxvxV.~'~* * Scryn, Swordbearer, Rennard, Tricops, and Gorog. | * * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik Staerfeldt, Tom Madsen, and Katja Nyboe. * ****************************************************************************/ #include "stdafx.h" #include "smaug.h" #include "objects.h" #include "rooms.h" #include "editor.h" #include "SmaugWizDoc.h" #include "descriptor.h" #include "character.h" void start_editing (CCharacter *ch, const char *data) { CEditor *edit; if (!ch->GetDesc ()) { bug ("Fatal: start_editing: no desc"); return; } if (ch->GetSubstate () == SUB_RESTRICTED) bug ("NOT GOOD: start_editing: ch->substate == SUB_RESTRICTED"); set_char_color (AT_GREEN, ch); ch->SendText ("Begin entering your text now (/? = help /s = save /c = clear /l = list)\n\r"); ch->SendText ("-----------------------------------------------------------------------\n\r> "); // if we're already editing something, stop it. ch->StopEditing (); edit = new CEditor; edit->Init (data); ch->SetEditor (edit); edit->Edit (*ch, "/l"); // show text at start ch->GetDesc ()->m_Connected = CON_EDITING; } void CEditor::Init (const char *data) { int size = 0; int lpos = 0; int lines = 0; char c; if (! data) { bug ("editor: data is NULL!\n\r"); return; } for (;;) { c = data [size++]; if (c == '\0') { m_Buf [lines][lpos] = '\0'; break; } else if (c == '\r'); else if (c == '\n' || lpos > 78) { m_Buf [lines][lpos] = '\0'; ++lines; lpos = 0; } else m_Buf [lines][lpos++] = c; if (lines >= 49 || size > 4096) { m_Buf [lines][lpos] = '\0'; break; } } if (lpos) then ++lines; // if last line has no '\n', count it anyway m_Numlines = lines; m_Size = size; m_OnLine = lines; } // Simple but nice and handle line editor. -Thoric void CEditor::Edit (CCharacter &Ch, char *argument) { char cmd [MAX_INPUT_LENGTH]; char buf [MAX_INPUT_LENGTH]; short x, line, max_buf_lines; CDescriptor &Ds = *Ch.GetDesc (); if (Ch.GetSubstate () <= SUB_PAUSE) { Ch.SendText ("You can't do that!\n\r"); bug ("Edit_buffer: illegal Ch.substate (%d)", Ch.GetSubstate ()); Ds.m_Connected = CON_PLAYING; return; } BOOL bSave = FALSE; max_buf_lines = 24; if (Ch.GetSubstate () == SUB_MPROG_EDIT || Ch.GetSubstate () == SUB_HELP_EDIT) max_buf_lines = 48; if (argument [0] == '/' || argument [0] == '\\') { one_argument (argument, cmd); if (! str_cmp (cmd+1, "?")) { Ch.SendText ("Editing commands\n\r----------------------------" "-----\n\r"); Ch.SendText ("/l list buffer\n\r"); Ch.SendText ("/c clear buffer\n\r"); Ch.SendText ("/d [line] delete line\n\r"); Ch.SendText ("/g <line> goto line\n\r"); Ch.SendText ("/i <line> insert line\n\r"); Ch.SendText ("/r <old> <new> global replace\n\r"); Ch.SendText ("/a abort editing\n\r"); if (Ch.GetTrustLevel () > LEVEL_IMMORTAL) Ch.SendText ("/! <command> execute command (do not " "use another editing command)\n\r"); Ch.SendText ("/s save buffer\n\r\n\r> "); return; } if (! str_cmp (cmd+1, "c")) { Clear (); Ch.SendText ("Buffer cleared.\n\r> "); return; } if (! str_cmp (cmd+1, "r")) { char word1 [MAX_INPUT_LENGTH]; char word2 [MAX_INPUT_LENGTH]; char *sptr, *wptr, *lwptr; int x, count, wordln, word2ln, lineln; sptr = one_argument (argument, word1); sptr = one_argument (sptr, word1); sptr = one_argument (sptr, word2); if (word1 [0] == '\0' || word2 [0] == '\0') { Ch.SendText ("Need word to replace, and replacement.\n\r> "); return; } if (strcmp (word1, word2) == 0) { Ch.SendText ("Done.\n\r> "); return; } count = 0; wordln = strlen (word1); word2ln = strlen (word2); Ch.SendTextf ("Replacing all occurrences of %s with %s...\n\r", word1, word2); for (x = m_OnLine; x < m_Numlines; x++) { lwptr = m_Buf [x]; while ((wptr = strstr (lwptr, word1)) != NULL) { sptr = lwptr; lwptr = wptr + wordln; sprintf (buf, "%s%s", word2, wptr + wordln); lineln = wptr - m_Buf [x] - wordln; ++count; if (strlen (buf) + lineln > 79) { lineln = UMAX (0, (79 - strlen (buf))); buf [lineln] = '\0'; break; } else lineln = strlen (buf); buf [lineln] = '\0'; strcpy (wptr, buf); } } Ch.SendTextf ("Found and replaced %d occurrence (s).\n\r> ", count); return; } if (! str_cmp (cmd+1, "i")) { if (m_Numlines >= max_buf_lines) Ch.SendText ("Buffer is full.\n\r> "); else { if (argument [2] == ' ') line = atoi (argument + 2) - 1; else line = m_OnLine; if (line < 0) line = m_OnLine; if (line < 0 || line > m_Numlines) Ch.SendText ("Out of range.\n\r> "); else { for (x = ++m_Numlines; x > line; x--) strcpy (m_Buf [x], m_Buf [x-1]); strcpy (m_Buf [line], ""); Ch.SendText ("Line inserted.\n\r> "); } } return; } if (! str_cmp (cmd+1, "d")) { if (m_Numlines == 0) Ch.SendText ("Buffer is empty.\n\r> "); else { if (argument [2] == ' ') line = atoi (argument + 2) - 1; else line = m_OnLine; if (line < 0) line = m_OnLine; if (line < 0 || line > m_Numlines) Ch.SendText ("Out of range.\n\r> "); else { if (line == 0 && m_Numlines == 1) { Clear (); Ch.SendText ("Line deleted.\n\r> "); return; } for (x = line; x < (m_Numlines - 1); x++) strcpy (m_Buf [x], m_Buf [x+1]); strcpy (m_Buf [m_Numlines--], ""); if (m_OnLine > m_Numlines) m_OnLine = m_Numlines; Ch.SendText ("Line deleted.\n\r> "); } } return; } if (! str_cmp (cmd+1, "g")) { if (m_Numlines == 0) Ch.SendText ("Buffer is empty.\n\r> "); else { if (argument [2] == ' ') line = atoi (argument + 2) - 1; else { Ch.SendText ("Goto what line?\n\r> "); return; } if (line < 0) line = m_OnLine; if (line < 0 || line > m_Numlines) Ch.SendText ("Out of range.\n\r> "); else { m_OnLine = line; Ch.SendTextf ("(On line %d)\n\r> ", line+1); } } return; } if (! str_cmp (cmd+1, "l")) { if (m_Numlines == 0) Ch.SendText ("Buffer is empty.\n\r> "); else { Ch.SendText ("------------------\n\r"); for (x = 0; x < m_Numlines; x++) Ch.SendTextf ("%2d> %s\n\r", x+1, m_Buf [x]); Ch.SendText ("------------------\n\r> "); } return; } if (! str_cmp (cmd+1, "a")) { if (Ch.IsMenuActive ()) { Ch.ReturnToMenu (FALSE); return; } Ch.SendText ("\n\rAborting... "); StopEditing (Ch); return; } if (Ch.GetTrustLevel () > LEVEL_IMMORTAL && !str_cmp (cmd+1, "!")) { DO_FUN *last_cmd; int substate = Ch.GetSubstate (); last_cmd = Ch.last_cmd; Ch.SetSubstate (SUB_RESTRICTED); interpret (&Ch, argument+3); Ch.SetSubstate (substate); Ch.last_cmd = last_cmd; set_char_color (AT_GREEN, &Ch); Ch.SendText ("\n\r> "); return; } if (! str_cmp (cmd+1, "s")) { Ds.m_Connected = CON_PLAYING; if (Ch.IsMenuActive ()) { Ch.ReturnToMenu (TRUE); return; } if (Ch.last_cmd) (*Ch.last_cmd) (&Ch, ""); return; } } if (m_Size + strlen (argument) + 1 >= MAX_STRING_LENGTH - 1) Ch.SendText ("Your buffer is full.\n\r"); else { if (strlen (argument) > 79) { strncpy (buf, argument, 79); buf [79] = 0; Ch.SendText ("(Long line trimmed)\n\r> "); } else strcpy (buf, argument); strcpy (m_Buf [m_OnLine++], buf); if (m_OnLine > m_Numlines) m_Numlines++; if (m_Numlines > max_buf_lines) { m_Numlines = max_buf_lines; Ch.SendText ("Buffer full.\n\r"); bSave = TRUE; } } if (bSave) { Ds.m_Connected = CON_PLAYING; if (Ch.IsMenuActive ()) { Ch.ReturnToMenu (TRUE); return; } if (Ch.last_cmd) (*Ch.last_cmd) (&Ch, ""); return; } Ch.SendText ("> "); } char *CEditor::CopyToBuffer () { char buf [MAX_STRING_LENGTH]; char tmp [100]; short x, len; buf [0] = '\0'; for (x = 0; x < m_Numlines; x++) { strcpy (tmp, m_Buf [x]); smush_tilde (tmp); len = strlen (tmp); if (len && tmp [len-1] == '~') tmp [len-1] = '\0'; else strcat (tmp, "\r\n"); strcat (buf, tmp); } return STRALLOC (buf); } void CEditor::StopEditing (CCharacter& Ch) { set_char_color (AT_PLAIN, &Ch); Ch.SendText ("Done.\n\r"); Ch.dest_buf = NULL; Ch.spare_ptr = NULL; Ch.SetSubstate (SUB_NONE); if (!Ch.GetDesc ()) bug ("CEditor::StopEditing: no desc"); else Ch.GetDesc ()->m_Connected = CON_PLAYING; Ch.SetEditor (NULL); delete this; }