(****

 *
 * Module Edit defines the objects and operations related to generic editing
 * in the calendar system.
 *
 *)

object Clipboard is
    components: string;
    description: (*
        The clipboard holds a selection of cut or copied text.
    *);
end Clipboard;

object Selection is
    components: start_position:integer and end_position:integer and
        context:string;
    description: (*
        The workspace text selection is defined as the starting and editing
        character positions in current workspace text context.
    *);
end Selection;

object SelectionContext is
    components: string;
    description: (*
        SelectionContext is the text context in which the user makes a
        selection.
    *);
end SelectionContext;

operation EditUndo is
    inputs: uws:UserWorkSpace;
    outputs: uws':UserWorkSpace;

    description: (*
        Undo the most recent class operation.
    *);

    precondition:
        (*
         * The Previous stack is not empty.
         *)
        (uws.previous_stack != nil);

    postcondition:
        (*
         * The state of the current grade book is the previous state, and vice
         * versa.
         *)
        (uws' = uws.previous_stack[1]) and
        (uws'.previous_stack[1] = uws.previous_stack[2]);

end EditUndo;

operation EditRedo is
    inputs: uws:UserWorkSpace;
    outputs: uws':UserWorkSpace;

    description: (*
        Redo the last Undo.
    *);

    precondition:
        (*
         * The Next stack is not empty.
         *)
        (uws.next_stack != nil);

    postcondition:
        (*
         * The state of the current grade book is the next state, and vice
         * versa.
         *)
       (uws' = uws.next_stack[1]) and
        (uws'.next_stack[1] = uws.next_stack[2]);

end EditRedo;

operation EditCut is
    inputs: uws:UserWorkSpace;
    outputs: uws':UserWorkSpace;

    description: (*
        The currently selected text segment is copied into the clipboard and
        removed from its context. The workspace selection is set to empty.
    *);

    precondition:
        (*
         * The selection is not empty.
         *)
        uws.selection != nil;

    postcondition:
        (*
         * The clipboard of the output workspace equals the selection. The
         * selection context of the output workspace has the selection removed.
         * The selection of the output workspace is nil.
         *)
        (uws'.clipboard = uws.context[
            uws.selection.start_position:uws.selection.end_position])

            and

        (uws'.context = uws.context[1:uws.selection.start_position-1] +
                        uws.context[uws.selection.start_position+1:
                                    #(uws.context)])

            and

        (uws'.selection = nil);

end EditCut;

operation EditCopy is
    inputs: uws:UserWorkSpace;
    outputs: uws':UserWorkSpace;

    description: (*
        The currently selected text segment is copied into the clipboard.
    *);

    precondition:
        (*
         * The selection is not empty.
         *)
        uws.selection != nil;

    postcondition:
        (*
         * The clipboard of the output workspace equals the selection. The
         * context and selection of the output workspace are unchanged.
         *)
        (uws'.clipboard = uws.context[
            uws.selection.start_position:uws.selection.end_position])

            and

        (uws'.context = uws.context)

            and

        (uws'.selection = uws.selection);

end EditCopy;

operation EditPaste is
    inputs: uws:UserWorkSpace;
    outputs: uws':UserWorkSpace;

    description: (*
        Paste the contents of the clipboard into the currently selected
        start position, replacing any selected text from start to end position.
    *);

    precondition:
        (*
         * The clipboard is not empty.
         *)
        uws.clipboard != nil;

    postcondition:
        (*
         * The context in the output workspace is the string consisting of
         * everything up to the selection, followed by the clipboard, followed
         * by everything after selection. The selection of the output workspace
         * is nil and the clipboard is unchanged.
         *)
        (uws'.clipboard = uws.context[1:uws.selection.start_position-1] +
                          uws.clipboard +
                          uws.context[uws.selection.start_position+1:
                                      #(uws.context)])

            and

        (uws'.selection = nil)

            and

        (uws'.clipboard = uws.clipboard);

end EditPaste;

operation EditPreferences is
    inputs: uws:UserWorkSpace;
    outputs: uws':UserWorkSpace;

    description: (*
        Edit preferences for current workspace.
    *);

    precondition: (* None yet. *);

    postcondition:
        (*
         * The workspace is changed.
         *);

end EditPreferences;