/
CDC-1.2b/
CDC-1.2b/src/
parent $editors
object $generic_editor

var $root child_index 0
var $root owners [$generic_editor]
var $root owned [$generic_editor]
var $root fertile 0
var $has_commands commands [["@abort|abort", 'abort_cmd], ["quit|@quit", 'quit_cmd], ["list|nlist *", 'list_cmd], ["ins?ert *", 'insert_cmd], ["del?ete *", 'del_line_cmd], ["join *", 'join_cmd], ["enter", 'enter_cmd], ["help", 'help_screen]]
var $has_commands shortcuts [["\"*", 'add_line_cmd, [1]], ["s/*/*", 'sub_cmd, ["", 1, 2]], ["fill * @*", 'fill_cmd, ["", 1, 2]], ["fill *", 'fill_cmd, ["", 1, ""]]]
var $command_aliases command_aliases []
var $root inited 1
var $generic_editor pass_through 0
var $root manager $generic_editor
var $root writable [$generic_editor]
var $root readable ['parameters, 'methods, 'code]
var $root dbref 'generic_editor
var $old_command_environment verb_cache #[]
var $old_command_environment command_cache [["@abort|abort", 'abort_cmd], ["quit|@quit", 'quit_cmd], ["list|nlist *", 'list_cmd], ["ins?ert *", 'insert_cmd], ["del?ete *", 'del_line_cmd], ["join *", 'join_cmd], ["enter", 'enter_cmd], ["help", 'help_screen]]
var $old_command_environment shortcuts_cache [["\"*", 'add_line_cmd, [1]], ["s/*/*", 'sub_cmd, ["", 1, 2]], ["fill * @*", 'fill_cmd, ["", 1, 2]], ["fill *", 'fill_cmd, ["", 1, ""]]]

method start_editing
    arg what;
    
    // called by user.edit_cmd
    sender().tell([("The selected editor, " + (.namef('id))) + "must define .start_editing()."]);
    return 0;
.

method parse_command
    arg str;
    var cmd, loc, result, i, j, templates, template, word, fields, obj, verb_info, subbed_str;
    
    // This method works like $user.parse_command
    // The difference is that the permissions have changed, and after checking aliases and
    // commands, and nothing was found, resorting to sender().match_command() is an option.
    if (((sender().editor()) != this()) || (caller() != $user_input))
        throw(~perm, "Invalid access to parse_command.");
    
    // remove leading spaces, abort on blank line
    subbed_str = str;
    while (subbed_str && ((subbed_str[1]) == " "))
        subbed_str = substr(subbed_str, 2);
    if (!subbed_str)
        return sender().editing();
    
    // sub the string through command aliases first
    subbed_str = .match_command_aliases(subbed_str);
    
    // Check commands on this.
    cmd = .match_command(subbed_str);
    if (cmd)
        return .(cmd[1])(sender().editing(), @cmd[2]);
    
    // if we're passing unknowns on to user.parse_command()...
    if (pass_through) {
        sender().tell("(Still editing.)");
        sender().run_with_users_perms(sender(), 'parse_command, str);
    } else {
        sender().tell("I don't understand that.");
    }
    return sender().editing();
.

method abort_cmd
    arg editing, com;
    
    .perms(sender(), 'parser);
    if (type(editing) == 'dict) {
        if (editing['changed])
            (editing['user]).tell("Threw away changes and cleared editor variables.");
        else
            (editing['user]).tell("No changes to throw away. Cleared editor variables.");
    } else {
        (| $admin_2.tell(((.namef('id)) + ": editing corrupeted, == ") + ($data.unparse(editing))) |);
    }
    return 0;
.

method quit_cmd
    arg editing, com;
    
    .perms(sender(), 'parser);
    if (editing['changed]) {
        (editing['user]).tell("Changes have been made. Save first, or abort to cancel.");
        return editing;
    } else {
        (editing['user]).tell("Quiting editor.");
        return 0;
    }
.

method adjust
    arg text, [how];
    var line;
    
    for line in [1 .. listlen(text)] {
        if ('spaces in how)
            text = replace(text, line, " " + (text[line]));
        if ('numbers in how)
            text = replace(text, line, (($string.right(tostr(line), 3)) + " :") + (text[line]));
    }
    return text;
.

method list_cmd
    arg editing, com, rest;
    var line, text;
    
    .perms(sender(), 'parser);
    if (com == "list") {
        (editing['user]).tell(editing['text]);
    } else {
        text = $generic_editor.adjust(editing['text], 'numbers);
        for line in [1 .. listlen(text)] {
            if (line == ((editing['cur_line]) - 1))
                (editing['user]).tell((strsub($string.right(tostr(line), 3), " ", "_") + "_:") + ((editing['text])[line]));
            else if (line == (editing['cur_line]))
                (editing['user]).tell((strsub($string.right(tostr(line), 3), " ", "^") + "^:") + ((editing['text])[line]));
            else
                (editing['user]).tell(text[line]);
        }
    }
    return editing;
.

method insert_cmd
    arg editing, com, [args];
    var line, text;
    
    // re-position and (eventually/optionally) add text
    .perms(sender(), 'parser);
    line = [@args, ""][1];
    text = [@args, "", ""][2];
    if (!line) {
        (editing['user]).tell(["Syntax: ins*ert line [text]", "!   You must supply a line number."]);
        return editing;
    }
    if (line != "$")
        line = toint(line);
    else
        line = listlen(editing['text]) + 1;
    if (!line) {
        (editing['user]).tell(["Syntax: ins*ert line [text]", "!   You must supply a line number greater than or equal to 1."]);
        return editing;
    }
    if (line > (listlen(editing['text]) + 1))
        line = listlen(editing['text]) + 1;
    editing = editing.replace('cur_line, line);
    ._show_line(editing);
    return editing;
.

method _show_line
    arg editing;
    var line;
    
    line = (editing['cur_line]) - 1;
    if (line)
        (editing['user]).tell((strsub($string.right(tostr(line), 3), " ", "_") + "_:") + ((editing['text])[line]));
    else
        (editing['user]).tell("____");
    line = line + 1;
    if (line <= listlen(editing['text]))
        (editing['user]).tell((strsub($string.right(tostr(line), 3), " ", "^") + "^:") + ((editing['text])[line]));
    else
        (editing['user]).tell("^^^^");
    return editing;
.

method insert_line
    arg editing, line;
    
    // insert line at editing['cur_line]
    // assumes editing['cur_line] is within 1 .. listlen(editing['text])
    .perms(sender(), 'this);
    editing = editing.replace('text, insert(editing['text], editing['cur_line], line));
    editing = editing.replace('cur_line, (editing['cur_line]) + 1);
    editing = editing.replace('changed, 1);
    return editing;
.

method add_line_cmd
    arg editing, line;
    
    // "*
    .perms(sender(), 'parser);
    editing = .insert_line(editing, line);
    
    // ._show_line(editing);
    (editing['user]).tell(("Added line " + tostr((editing['cur_line]) - 1)) + ".");
    return editing;
.

method delete_line
    arg editing;
    
    // delete line at editing['cur_line]
    // assumes editing['cur_line] is within 1 .. listlen(editing['text])
    .perms(sender(), 'this);
    editing = editing.replace('text, delete(editing['text], editing['cur_line]));
    editing = editing.replace('changed, 1);
    editing = editing.replace('cur_line, $list.min(editing['cur_line], listlen(editing['text])));
    return editing;
.

method del_line_cmd
    arg editing, com, line;
    
    // del?ete line_num
    .perms(sender(), 'parser);
    line = toint(line) || (editing['cur_line]);
    if (line <= (editing['cur_line])) {
        editing = editing.replace('cur_line, line);
        (editing['user]).tell(((("Removed line " + tostr(editing['cur_line])) + ": \"") + ((editing['text])[line])) + "\".");
        editing = .delete_line(editing);
    } else {
        (editing['user]).tell("Line number out of range.");
    }
    
    //._show_line(editing);
    return editing;
.

method sub_cmd
    arg editing, com, was, is;
    
    // s/from/to/
    editing = editing.replace('text, replace(editing['text], (editing['cur_line]) - 1, strsub((editing['text])[(editing['cur_line]) - 1], was, is)));
    ._show_line(editing);
    return editing;
.

method fill_cmd
    arg editing, com, range, [col];
    var start, current, stop, new_text, idx;
    
    col = toint([@col, "75"][1]) || 75;
    if ("-" in range) {
        start = toint(range);
        if (!start) {
            (editing['user]).tell("Must supply a valid range, such as 10, 2-3, or 1-$.");
            return editing;
        }
        range = substr(range, strlen(tostr(start)) + 2);
        if ((!range) || (range == "$"))
            stop = listlen(editing['text]);
        else
            stop = toint(range);
    } else {
        if (!range)
            start = editing['cur_line];
        else
            start = toint(range);
        if (!start) {
            (editing['user]).tell("Must supply a valid range, such as 10, 2-3, or 1-$.");
            return editing;
        }
        stop = start;
    }
    
    // actual change:
    new_text = editing['text];
    current = start;
    while (current <= stop) {
        if (strlen(new_text[current]) > col) {
            idx = col;
            while (idx && (((new_text[current])[idx]) != " "))
                idx = idx - 1;
            if (!idx) {
                idx = col + 1;
                while ((idx < strlen(new_text[current])) && (((new_text[current])[idx]) != " "))
                    idx = idx + 1;
                if (idx == strlen(new_text[current]))
                    idx = col;
            }
            new_text = insert(new_text, current + 1, substr(new_text[current], idx + 1));
            new_text = replace(new_text, current, substr(new_text[current], 1, idx));
            stop = stop + 1;
        }
        current = current + 1;
    }
    editing = editing.replace('text, new_text);
    editing = editing.replace('cur_line, stop + 1);
    new_text = $generic_editor.adjust(editing['text], 'numbers);
    for current in [start .. stop - 1]
        (editing['user]).tell(new_text[current]);
    ._show_line(editing);
    return editing;
.

method join_cmd
    arg editing, com, range;
    var start, stop, current, new_text;
    
    new_text = editing['text];
    start = toint(range);
    range = substr(range, strlen(tostr(start)) + 2);
    stop = toint(range);
    if (range == "$")
        stop = listlen(new_text);
    if ((!start) || (!stop)) {
        (editing['user]).tell("Syntax: join <range>");
        (editing['user]).tell("!   You must supply a range of lines to join, such as 3-4 or 1-$");
        return editing;
    }
    stop = $list.min(stop, listlen(new_text));
    
    // actual change:
    while (start < stop) {
        new_text = replace(new_text, start, (new_text[start]) + (new_text[start + 1]));
        new_text = delete(new_text, start + 1);
        stop = stop - 1;
    }
    editing = editing.replace('text, new_text);
    editing = editing.replace('cur_line, stop + 1);
    ._show_line(editing);
    return editing;
.

method enter_cmd
    arg editing, com;
    
    (editing['user]).read('done_entering, editing);
    return editing;
.

method done_entering
    arg text, editing;
    
    if (sender() != (editing['user]))
        throw(~perm, "Invalid access to done_entering.");
    if (listlen(text)) {
        if (listlen(text) > 1)
            (editing['user]).tell(((("Added lines " + tostr(editing['cur_line])) + " .. ") + tostr(((editing['cur_line]) + listlen(text)) - 1)) + ".");
        else
            (editing['user]).tell(("Added line " + tostr(editing['cur_line])) + ".");
        while (text) {
            editing = editing.replace('text, insert(editing['text], text[1], editing['cur_line]));
            editing = editing.replace('cur_line, (editing['cur_line]) + 1);
            text = delete(test, 1);
        }
    }
.

method help_msg
    var msg;
    
    msg = [];
    msg = msg + ["  ins?ert *    set line number"];
    msg = msg + ["  del?ete *    delete line"];
    msg = msg + ["  \"*           insert text"];
    msg = msg + ["  abort        cancel changes and exit editor"];
    msg = msg + ["  quit         exit if no changes made since last save"];
    msg = msg + ["  list|nlist   list text without|with numbers"];
    msg = msg + ["  s/*/*        str sub: replace first with second in current line."];
    msg = msg + ["  fill * [@*]  wrap lines (@ col, def: 75)"];
    msg = msg + ["  join *       concatonates a range of lines"];
    return msg;
.

method help_screen
    arg editing, com;
    
    // l?ook
    .perms(sender(), 'this);
    (editing['user]).tell(.help_msg());
.