diff options
author | Guido van Rossum <guido@python.org> | 1992-03-30 10:54:51 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1992-03-30 10:54:51 (GMT) |
commit | 9cf8f3372c3b7896b085e590c1a11373b58695fb (patch) | |
tree | 024c99b4964dee21aa8bb0f37f641f5b18bad2cc /Demo/stdwin/miniedit.py | |
parent | 7ebb23c6375a028eb8a5f0a20a2e04652b977803 (diff) | |
download | cpython-9cf8f3372c3b7896b085e590c1a11373b58695fb.zip cpython-9cf8f3372c3b7896b085e590c1a11373b58695fb.tar.gz cpython-9cf8f3372c3b7896b085e590c1a11373b58695fb.tar.bz2 |
Initial revision
Diffstat (limited to 'Demo/stdwin/miniedit.py')
-rwxr-xr-x | Demo/stdwin/miniedit.py | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/Demo/stdwin/miniedit.py b/Demo/stdwin/miniedit.py new file mode 100755 index 0000000..3e8da2b --- /dev/null +++ b/Demo/stdwin/miniedit.py @@ -0,0 +1,356 @@ +#! /usr/local/python + +# A miniature multi-window editor using STDWIN's text objects. +# +# Usage: miniedit [file] ... +# +# The user interface is similar to that of the miniedit demo application +# in C that comes with STDWIN. +# +# XXX need to comment the functions +# XXX Not yet implemented: +# disabling menu entries for inapplicable actions +# Find operations + + +import sys +import stdwin +from stdwinevents import * + + +# Constant: list of WE_COMMAND events that (may) change the text buffer +# so we can decide whether to set the 'changed' flag. +# Note that it is possible for such a command to fail (a backspace +# at the beginning of the buffer) but we'll set the changed flag anyway +# -- it's too complicated to check this condition right now. +# +changing = [WC_RETURN, WC_TAB, WC_BACKSPACE] + + +# The list of currently open windows; +# this is maintained so we can stop when there are no windows left +# +windows = [] + + +# A note on window data attributes (set by open_window): +# +# w.textobject the window's text object +# w.changed true when the window's text is changed +# w.filename filename connected to the window; '' if none + + +# Main program +# +def main(): + # + # Set a reasonable default window size. + # If we are using a fixed-width font this will open a 80x24 window; + # for variable-width fonts we approximate this based on an average + # + stdwin.setdefwinsize(40*stdwin.textwidth('in'), 24*stdwin.lineheight()) + # + # Create global menus (as local variables) + # + filemenu = make_file_menu(stdwin) + editmenu = make_edit_menu(stdwin) + findmenu = make_find_menu(stdwin) + # + # Get the list of files from the command line (maybe none) + # + files = sys.argv[1:] + # + # Open any files -- errors will be reported but do won't stop us + # + for filename in files: + open_file(filename) + # + # If there were no files, or none of them could be opened, + # put up a dialog asking for a filename + # + if not windows: + try: + open_dialog(None) + except KeyboardInterrupt: + pass # User cancelled + # + # If the dialog was cancelled, create an empty new window + # + if not windows: + new_window(None) + # + # Main event loop -- stop when we have no open windows left + # + while windows: + # + # Get the next event -- ignore interrupts + # + try: + type, window, detail = event = stdwin.getevent() + except KeyboardInterrupt: + type, window, detail = event = WE_NONE, None, None + # + # Event decoding switch + # + if not window: + pass # Ignore such events + elif type == WE_MENU: + # + # Execute menu operation + # + menu, item = detail + try: + menu.actions[item](window) + except KeyboardInterrupt: + pass # User cancelled + elif type == WE_CLOSE: + # + # Close a window + # + try: + close_dialog(window) + except KeyboardInterrupt: + pass # User cancelled + elif type == WE_SIZE: + # + # A window was resized -- + # let the text object recompute the line breaks + # and change the document size accordingly, + # so scroll bars will work + # + fix_textsize(window) + elif window.textobject.event(event): + # + # The event was eaten by the text object -- + # set the changed flag if not already set + # + if type == WE_CHAR or \ + type == WE_COMMAND and detail in changing: + window.changed = 1 + fix_docsize(window) + # + # Delete all objects that may still reference the window + # in the event -- this is needed otherwise the window + # won't actually be closed and may receive further + # events, which will confuse the event decoder + # + del type, window, detail, event + + +def make_file_menu(object): + menu = object.menucreate('File') + menu.actions = [] + additem(menu, 'New', 'N', new_window) + additem(menu, 'Open..', 'O', open_dialog) + additem(menu, '', '', None) + additem(menu, 'Save', 'S', save_dialog) + additem(menu, 'Save As..', '', save_as_dialog) + additem(menu, 'Save a Copy..', '', save_copy_dialog) + additem(menu, 'Revert', 'R', revert_dialog) + additem(menu, 'Quit', 'Q', quit_dialog) + return menu + + +def make_edit_menu(object): + menu = object.menucreate('Edit') + menu.actions = [] + additem(menu, 'Cut', 'X', do_cut) + additem(menu, 'Copy', 'C', do_copy) + additem(menu, 'Paste', 'V', do_paste) + additem(menu, 'Clear', 'B', do_clear) + additem(menu, 'Select All', 'A', do_select_all) + return menu + + +def make_find_menu(object): + menu = object.menucreate('Find') + menu.actions = [] + # XXX + return menu + + +def additem(menu, text, shortcut, function): + if shortcut: + menu.additem(text, shortcut) + else: + menu.additem(text) + menu.actions.append(function) + + +def open_dialog(current_ignored): + filename = stdwin.askfile('Open file:', '', 0) + open_file(filename) + + +def open_file(filename): + try: + fp = open(filename, 'r') + except RuntimeError: + stdwin.message(filename + ': cannot open') + return # Error, forget it + try: + contents = fp.read() + except RuntimeError: + stdwin.message(filename + ': read error') + return # Error, forget it + del fp # Close the file + open_window(filename, filename, contents) + + +def new_window(current_ignored): + open_window('', 'Untitled', '') + + +def open_window(filename, title, contents): + try: + window = stdwin.open(title) + except RuntimeError: + stdwin.message('cannot open new window') + return # Error, forget it + window.textobject = window.textcreate((0, 0), window.getwinsize()) + window.textobject.settext(contents) + window.changed = 0 + window.filename = filename + fix_textsize(window) + windows.append(window) + + +def quit_dialog(window): + for window in windows[:]: + close_dialog(window) + + +def close_dialog(window): + if window.changed: + prompt = 'Save changes to ' + window.gettitle() + ' ?' + if stdwin.askync(prompt, 1): + save_dialog(window) + if window.changed: + return # Save failed (not) cancelled + windows.remove(window) + del window.textobject + + +def save_dialog(window): + if not window.filename: + save_as_dialog(window) + return + if save_file(window, window.filename): + window.changed = 0 + + +def save_as_dialog(window): + prompt = 'Save ' + window.gettitle() + ' as:' + filename = stdwin.askfile(prompt, window.filename, 1) + if save_file(window, filename): + window.filename = filename + window.settitle(filename) + window.changed = 0 + + +def save_copy_dialog(window): + prompt = 'Save a copy of ' + window.gettitle() + ' as:' + filename = stdwin.askfile(prompt, window.filename, 1) + void = save_file(window, filename) + + +def save_file(window, filename): + try: + fp = open(filename, 'w') + except RuntimeError: + stdwin.message(filename + ': cannot create') + return 0 + contents = window.textobject.gettext() + try: + fp.write(contents) + except RuntimeError: + stdwin.message(filename + ': write error') + return 0 + return 1 + + +def revert_dialog(window): + if not window.filename: + stdwin.message('This window has no file to revert from') + return + if window.changed: + prompt = 'Really read ' + window.filename + ' back from file?' + if not stdwin.askync(prompt, 1): + return + try: + fp = open(window.filename, 'r') + except RuntimeError: + stdwin.message(filename + ': cannot open') + return + contents = fp.read() + del fp # Close the file + window.textobject.settext(contents) + window.changed = 0 + fix_docsize(window) + + +def fix_textsize(window): + corner = window.getwinsize() + area = (0, 0), (corner) + window.textobject.move(area) + fix_docsize(window) + + +def fix_docsize(window): + area = window.textobject.getrect() + origin, corner = area + width, height = corner + window.setdocsize(0, height) + + +def do_cut(window): + selection = window.textobject.getfocustext() + if not selection: + stdwin.fleep() # Nothing to cut + elif not window.setselection(WS_PRIMARY, selection): + stdwin.fleep() # Window manager glitch... + else: + stdwin.rotatecutbuffers(1) + stdwin.setcutbuffer(0, selection) + window.textobject.replace('') + window.changed = 1 + fix_docsize(window) + + +def do_copy(window): + selection = window.textobject.getfocustext() + if not selection: + stdwin.fleep() # Nothing to cut + elif not window.setselection(WS_PRIMARY, selection): + stdwin.fleep() # Window manager glitch... + else: + stdwin.rotatecutbuffers(1) + stdwin.setcutbuffer(0, selection) + + +def do_paste(window): + selection = stdwin.getselection(WS_PRIMARY) + if not selection: + selection = stdwin.getcutbuffer(0) + if not selection: + stdwin.fleep() # Nothing to paste + else: + window.textobject.replace(selection) + window.changed = 1 + fix_docsize(window) + +def do_clear(window): + first, last = window.textobject.getfocus() + if first == last: + stdwin.fleep() # Nothing to clear + else: + window.textobject.replace('') + window.changed = 1 + fix_docsize(window) + + +def do_select_all(window): + window.textobject.setfocus(0, 0x7fffffff) # XXX Smaller on the Mac! + + +main() |