1992-12-14 15:12:10 +01:00
|
|
|
#! /usr/local/bin/python
|
1992-03-30 12:54:51 +02:00
|
|
|
|
|
|
|
# A minimal single-window text editor using STDWIN's text objects.
|
|
|
|
#
|
|
|
|
# Usage: microedit file
|
|
|
|
#
|
|
|
|
# This is not intended as a real application but as an introduction
|
|
|
|
# to STDWIN programming in Python, especially text objects.
|
|
|
|
# Once you understand microedit.py, study miniedit.py to learn
|
|
|
|
# about multiple windows and menus, cut and paste, etc.
|
|
|
|
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import stdwin
|
|
|
|
from stdwinevents import *
|
|
|
|
|
|
|
|
|
|
|
|
# Main program
|
|
|
|
#
|
|
|
|
def main():
|
|
|
|
#
|
|
|
|
# Get the filename argument and read its contents as one very
|
|
|
|
# large string.
|
|
|
|
# An exception will terminate the program if there is no argument
|
|
|
|
# or if the file could not be read...
|
|
|
|
#
|
|
|
|
filename = sys.argv[1]
|
|
|
|
fp = open(filename, 'r')
|
|
|
|
contents = fp.read()
|
|
|
|
del fp # Close the file
|
|
|
|
#
|
|
|
|
# Create the window, using the filename as window title
|
|
|
|
#
|
|
|
|
window = stdwin.open(filename)
|
|
|
|
#
|
|
|
|
# Add a simple File menu to the window with two items
|
|
|
|
#
|
|
|
|
filemenu = window.menucreate('File')
|
|
|
|
filemenu.additem('Save', 'S') # Item 0 (shortcut Meta-S)
|
|
|
|
filemenu.additem('Save As...') # Item 1
|
|
|
|
#
|
|
|
|
# Create a text object occupying the entire window
|
|
|
|
# and fill it with the file's contents
|
|
|
|
#
|
|
|
|
corner = window.getwinsize() # (width, height)
|
|
|
|
area = (0, 0), corner # Rectangle as large as the window
|
|
|
|
text = window.textcreate(area)
|
|
|
|
text.settext(contents)
|
|
|
|
del contents # Get rid of contents object
|
|
|
|
fix_textsize(window, text) # Set document size accordingly
|
|
|
|
#
|
|
|
|
# Main event loop -- stop if a close request comes in.
|
|
|
|
#
|
|
|
|
# STDWIN applications should regularly call stdwin.getevent()
|
|
|
|
# otherwise the windows won't function as expected.
|
|
|
|
#
|
|
|
|
while 1:
|
|
|
|
#
|
|
|
|
# Get the next event
|
|
|
|
#
|
|
|
|
type, w, detail = e = stdwin.getevent()
|
|
|
|
#
|
|
|
|
# Event decoding switch
|
|
|
|
#
|
|
|
|
if type == WE_CLOSE:
|
|
|
|
break # Stop (no check for saved file!)
|
|
|
|
elif type == WE_SIZE:
|
|
|
|
#
|
|
|
|
# The 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, text)
|
|
|
|
elif type == WE_MENU:
|
|
|
|
#
|
|
|
|
# Execute a file menu request (our only menu)
|
|
|
|
#
|
|
|
|
menu, item = detail
|
|
|
|
if item == 0:
|
|
|
|
#
|
|
|
|
# "Save": save to the current filename
|
|
|
|
#
|
|
|
|
dummy = save_file(window, text, filename)
|
|
|
|
elif item == 1:
|
|
|
|
#
|
|
|
|
# "Save As": ask a new filename, save to it,
|
|
|
|
# and make it the current filename
|
|
|
|
#
|
|
|
|
# NB: askfile raises KeyboardInterrupt
|
|
|
|
# if the user cancels the dialog, hence
|
|
|
|
# the try statement
|
|
|
|
#
|
|
|
|
try:
|
|
|
|
newfile = stdwin.askfile( \
|
|
|
|
'Save as:', filename, 1)
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
newfile = ''
|
|
|
|
if newfile:
|
|
|
|
if save_file(window, text, newfile):
|
|
|
|
filename = newfile
|
|
|
|
window.settitle(filename)
|
|
|
|
elif text.event(e):
|
|
|
|
#
|
|
|
|
# The text object has handled the event.
|
|
|
|
# Fix the document size if necessary.
|
|
|
|
# Note: this sometimes fixes the size
|
|
|
|
# unnecessarily, e.g., for arrow keys.
|
|
|
|
#
|
|
|
|
if type in (WE_CHAR, WE_COMMAND):
|
|
|
|
fix_docsize(window, text)
|
|
|
|
|
|
|
|
|
|
|
|
# Save the window's contents to the filename.
|
|
|
|
# If the open() fails, put up a warning message and return 0;
|
|
|
|
# if the save succeeds, return 1.
|
|
|
|
#
|
|
|
|
def save_file(window, text, filename):
|
|
|
|
#
|
|
|
|
# Open the file for writing, handling exceptions
|
|
|
|
#
|
|
|
|
try:
|
|
|
|
fp = open(filename, 'w')
|
|
|
|
except RuntimeError:
|
|
|
|
stdwin.message('Cannot create ' + filename)
|
|
|
|
return 0
|
|
|
|
#
|
|
|
|
# Get the contents of the text object as one very long string
|
|
|
|
#
|
|
|
|
contents = text.gettext()
|
|
|
|
#
|
|
|
|
# Write the contents to the file
|
|
|
|
#
|
|
|
|
fp.write(contents)
|
|
|
|
#
|
|
|
|
# The file is automatically closed when this routine returns
|
|
|
|
#
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
|
|
# Change the size of the text object to fit in the window,
|
|
|
|
# and then fix the window's document size to fit around the text object.
|
|
|
|
#
|
|
|
|
def fix_textsize(window, text):
|
|
|
|
#
|
|
|
|
# Compute a rectangle as large as the window
|
|
|
|
#
|
|
|
|
corner = window.getwinsize() # (width, height)
|
|
|
|
area = (0, 0), (corner)
|
|
|
|
#
|
|
|
|
# Move the text object to this rectangle.
|
|
|
|
# Note: text.move() ignores the bottom coordinate!
|
|
|
|
#
|
|
|
|
text.move(area)
|
|
|
|
#
|
|
|
|
# Now fix the document size accordingly
|
|
|
|
#
|
|
|
|
fix_docsize(window, text)
|
|
|
|
|
|
|
|
|
|
|
|
# Fix the document size, after the text has changed
|
|
|
|
#
|
|
|
|
def fix_docsize(window, text):
|
|
|
|
#
|
|
|
|
# Get the actual rectangle occupied by the text object.
|
|
|
|
# This has the same left, top and right, but a different bottom.
|
|
|
|
#
|
|
|
|
area = text.getrect()
|
|
|
|
#
|
|
|
|
# Compute the true height of the text object
|
|
|
|
#
|
|
|
|
origin, corner = area
|
|
|
|
width, height = corner
|
|
|
|
#
|
|
|
|
# Set the document height to the text object's height.
|
|
|
|
# The width is zero since we don't want a horizontal scroll bar.
|
|
|
|
#
|
|
|
|
window.setdocsize(0, height)
|
|
|
|
|
|
|
|
|
|
|
|
# Once all functions are defined, call main()
|
|
|
|
#
|
|
|
|
main()
|