summaryrefslogtreecommitdiffstats
path: root/Demo/stdwin/miniedit.py
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1992-03-30 10:54:51 (GMT)
committerGuido van Rossum <guido@python.org>1992-03-30 10:54:51 (GMT)
commit9cf8f3372c3b7896b085e590c1a11373b58695fb (patch)
tree024c99b4964dee21aa8bb0f37f641f5b18bad2cc /Demo/stdwin/miniedit.py
parent7ebb23c6375a028eb8a5f0a20a2e04652b977803 (diff)
downloadcpython-9cf8f3372c3b7896b085e590c1a11373b58695fb.zip
cpython-9cf8f3372c3b7896b085e590c1a11373b58695fb.tar.gz
cpython-9cf8f3372c3b7896b085e590c1a11373b58695fb.tar.bz2
Initial revision
Diffstat (limited to 'Demo/stdwin/miniedit.py')
-rwxr-xr-xDemo/stdwin/miniedit.py356
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()