|
1120
|
1 #! /usr/local/bin/python
|
|
752
|
2
|
|
|
3 # A minimal single-window text editor using STDWIN's text objects.
|
|
|
4 #
|
|
|
5 # Usage: microedit file
|
|
|
6 #
|
|
|
7 # This is not intended as a real application but as an introduction
|
|
|
8 # to STDWIN programming in Python, especially text objects.
|
|
|
9 # Once you understand microedit.py, study miniedit.py to learn
|
|
|
10 # about multiple windows and menus, cut and paste, etc.
|
|
|
11
|
|
|
12
|
|
|
13 import sys
|
|
|
14 import stdwin
|
|
|
15 from stdwinevents import *
|
|
|
16
|
|
|
17
|
|
|
18 # Main program
|
|
|
19 #
|
|
|
20 def main():
|
|
|
21 #
|
|
|
22 # Get the filename argument and read its contents as one very
|
|
|
23 # large string.
|
|
|
24 # An exception will terminate the program if there is no argument
|
|
|
25 # or if the file could not be read...
|
|
|
26 #
|
|
|
27 filename = sys.argv[1]
|
|
|
28 fp = open(filename, 'r')
|
|
|
29 contents = fp.read()
|
|
|
30 del fp # Close the file
|
|
|
31 #
|
|
|
32 # Create the window, using the filename as window title
|
|
|
33 #
|
|
|
34 window = stdwin.open(filename)
|
|
|
35 #
|
|
|
36 # Add a simple File menu to the window with two items
|
|
|
37 #
|
|
|
38 filemenu = window.menucreate('File')
|
|
|
39 filemenu.additem('Save', 'S') # Item 0 (shortcut Meta-S)
|
|
|
40 filemenu.additem('Save As...') # Item 1
|
|
|
41 #
|
|
|
42 # Create a text object occupying the entire window
|
|
|
43 # and fill it with the file's contents
|
|
|
44 #
|
|
|
45 corner = window.getwinsize() # (width, height)
|
|
|
46 area = (0, 0), corner # Rectangle as large as the window
|
|
|
47 text = window.textcreate(area)
|
|
|
48 text.settext(contents)
|
|
|
49 del contents # Get rid of contents object
|
|
|
50 fix_textsize(window, text) # Set document size accordingly
|
|
|
51 #
|
|
|
52 # Main event loop -- stop if a close request comes in.
|
|
|
53 #
|
|
|
54 # STDWIN applications should regularly call stdwin.getevent()
|
|
|
55 # otherwise the windows won't function as expected.
|
|
|
56 #
|
|
|
57 while 1:
|
|
|
58 #
|
|
|
59 # Get the next event
|
|
|
60 #
|
|
|
61 type, w, detail = e = stdwin.getevent()
|
|
|
62 #
|
|
|
63 # Event decoding switch
|
|
|
64 #
|
|
|
65 if type == WE_CLOSE:
|
|
|
66 break # Stop (no check for saved file!)
|
|
|
67 elif type == WE_SIZE:
|
|
|
68 #
|
|
|
69 # The window was resized --
|
|
|
70 # let the text object recompute the line breaks
|
|
|
71 # and change the document size accordingly,
|
|
|
72 # so scroll bars will work
|
|
|
73 #
|
|
|
74 fix_textsize(window, text)
|
|
|
75 elif type == WE_MENU:
|
|
|
76 #
|
|
|
77 # Execute a file menu request (our only menu)
|
|
|
78 #
|
|
|
79 menu, item = detail
|
|
|
80 if item == 0:
|
|
|
81 #
|
|
|
82 # "Save": save to the current filename
|
|
|
83 #
|
|
|
84 dummy = save_file(window, text, filename)
|
|
|
85 elif item == 1:
|
|
|
86 #
|
|
|
87 # "Save As": ask a new filename, save to it,
|
|
|
88 # and make it the current filename
|
|
|
89 #
|
|
|
90 # NB: askfile raises KeyboardInterrupt
|
|
|
91 # if the user cancels the dialog, hence
|
|
|
92 # the try statement
|
|
|
93 #
|
|
|
94 try:
|
|
|
95 newfile = stdwin.askfile( \
|
|
|
96 'Save as:', filename, 1)
|
|
|
97 except KeyboardInterrupt:
|
|
|
98 newfile = ''
|
|
|
99 if newfile:
|
|
|
100 if save_file(window, text, newfile):
|
|
|
101 filename = newfile
|
|
|
102 window.settitle(filename)
|
|
|
103 elif text.event(e):
|
|
|
104 #
|
|
|
105 # The text object has handled the event.
|
|
|
106 # Fix the document size if necessary.
|
|
|
107 # Note: this sometimes fixes the size
|
|
|
108 # unnecessarily, e.g., for arrow keys.
|
|
|
109 #
|
|
|
110 if type in (WE_CHAR, WE_COMMAND):
|
|
|
111 fix_docsize(window, text)
|
|
|
112
|
|
|
113
|
|
|
114 # Save the window's contents to the filename.
|
|
|
115 # If the open() fails, put up a warning message and return 0;
|
|
|
116 # if the save succeeds, return 1.
|
|
|
117 #
|
|
|
118 def save_file(window, text, filename):
|
|
|
119 #
|
|
|
120 # Open the file for writing, handling exceptions
|
|
|
121 #
|
|
|
122 try:
|
|
|
123 fp = open(filename, 'w')
|
|
|
124 except RuntimeError:
|
|
|
125 stdwin.message('Cannot create ' + filename)
|
|
|
126 return 0
|
|
|
127 #
|
|
|
128 # Get the contents of the text object as one very long string
|
|
|
129 #
|
|
|
130 contents = text.gettext()
|
|
|
131 #
|
|
|
132 # Write the contents to the file
|
|
|
133 #
|
|
|
134 fp.write(contents)
|
|
|
135 #
|
|
|
136 # The file is automatically closed when this routine returns
|
|
|
137 #
|
|
|
138 return 1
|
|
|
139
|
|
|
140
|
|
|
141 # Change the size of the text object to fit in the window,
|
|
|
142 # and then fix the window's document size to fit around the text object.
|
|
|
143 #
|
|
|
144 def fix_textsize(window, text):
|
|
|
145 #
|
|
|
146 # Compute a rectangle as large as the window
|
|
|
147 #
|
|
|
148 corner = window.getwinsize() # (width, height)
|
|
|
149 area = (0, 0), (corner)
|
|
|
150 #
|
|
|
151 # Move the text object to this rectangle.
|
|
|
152 # Note: text.move() ignores the bottom coordinate!
|
|
|
153 #
|
|
|
154 text.move(area)
|
|
|
155 #
|
|
|
156 # Now fix the document size accordingly
|
|
|
157 #
|
|
|
158 fix_docsize(window, text)
|
|
|
159
|
|
|
160
|
|
|
161 # Fix the document size, after the text has changed
|
|
|
162 #
|
|
|
163 def fix_docsize(window, text):
|
|
|
164 #
|
|
|
165 # Get the actual rectangle occupied by the text object.
|
|
|
166 # This has the same left, top and right, but a different bottom.
|
|
|
167 #
|
|
|
168 area = text.getrect()
|
|
|
169 #
|
|
|
170 # Compute the true height of the text object
|
|
|
171 #
|
|
|
172 origin, corner = area
|
|
|
173 width, height = corner
|
|
|
174 #
|
|
|
175 # Set the document height to the text object's height.
|
|
|
176 # The width is zero since we don't want a horizontal scroll bar.
|
|
|
177 #
|
|
|
178 window.setdocsize(0, height)
|
|
|
179
|
|
|
180
|
|
|
181 # Once all functions are defined, call main()
|
|
|
182 #
|
|
|
183 main()
|