Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 18fc569

Browse files
committed
* mainloop.py: added facility for calling select(). Also added
embryonic facility for pseudo-modal dialogs. * stdwinevents.py: added modifier masks for key/mouse events * renamed exceptions in nntplib.py * Changed string.join() to call string.joinfields() to profit of strop.joinfields()
1 parent c89705d commit 18fc569

7 files changed

Lines changed: 374 additions & 28 deletions

File tree

Lib/lib-stdwin/mainloop.py

Lines changed: 166 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
windows = []
1414

1515

16+
# Last window that ever received an event
17+
#
18+
last_window = None
19+
20+
1621
# Function to register a window.
1722
#
1823
def register(win):
@@ -28,6 +33,9 @@ def register(win):
2833
# (this is useful for cleanup actions).
2934
#
3035
def unregister(win):
36+
global last_window
37+
if win == last_window:
38+
last_window = None
3139
if win in windows:
3240
windows.remove(win) # Not in 0.9.1
3341
# 0.9.1 solution:
@@ -49,6 +57,65 @@ def anywindow():
4957
return None
5058

5159

60+
# NEW: register any number of file descriptors
61+
#
62+
fdlist = []
63+
select_args = None
64+
select_handlers = None
65+
#
66+
def registerfd(fd, mode, handler):
67+
if mode not in ('r', 'w', 'x'):
68+
raise ValueError, 'mode must be r, w or x'
69+
if type(fd) <> type(0):
70+
fd = fd.fileno() # If this fails it's not a proper select arg
71+
for i in range(len(fdlist)):
72+
if fdlist[i][:2] == (fd, mode):
73+
raise ValueError, \
74+
'(fd, mode) combination already registered'
75+
fdlist.append((fd, mode, handler))
76+
make_select_args()
77+
#
78+
def unregisterfd(fd, *args):
79+
if type(fd) <> type(0):
80+
fd = fd.fileno() # If this fails it's not a proper select arg
81+
args = (fd,) + args
82+
n = len(args)
83+
for i in range(len(fdlist)):
84+
if fdlist[i][:n] == args:
85+
del fdlist[i]
86+
make_select_args()
87+
#
88+
def make_select_args():
89+
global select_args, select_handlers
90+
rlist, wlist, xlist = [], [], []
91+
rhandlers, whandlers, xhandlers = {}, {}, {}
92+
for fd, mode, handler in fdlist:
93+
if mode == 'r':
94+
rlist.append(fd)
95+
rhandlers[`fd`] = handler
96+
if mode == 'w':
97+
wlist.append(fd)
98+
whandlers[`fd`] = handler
99+
if mode == 'x':
100+
xlist.append(fd)
101+
xhandlers[`fd`] = handler
102+
if rlist or wlist or xlist:
103+
select_args = rlist, wlist, xlist
104+
select_handlers = rhandlers, whandlers, xhandlers
105+
else:
106+
select_args = None
107+
select_handlers = None
108+
#
109+
def do_select():
110+
import select
111+
reply = apply(select.select, select_args)
112+
for mode in 0, 1, 2:
113+
list = reply[mode]
114+
for fd in list:
115+
handler = select_handlers[mode][`fd`]
116+
handler(fd, 'rwx'[mode])
117+
118+
52119
# Event processing main loop.
53120
# Return when there are no windows left, or when an unhandled
54121
# exception occurs. (It is safe to restart the main loop after
@@ -57,17 +124,111 @@ def anywindow():
57124
# into KeyboardInterrupt exceptions; these are turned back in events.
58125
#
59126
def mainloop():
60-
while windows:
127+
stdwin_select_handler() # Process events already in stdwin queue
128+
fd = stdwin.fileno()
129+
while 1:
130+
if windows:
131+
registerfd(fd, 'r', stdwin_select_handler)
132+
try:
133+
while windows:
134+
do_select()
135+
stdwin_select_handler()
136+
finally:
137+
unregisterfd(fd)
138+
elif fdlist:
139+
while fdlist and not windows:
140+
do_select()
141+
else:
142+
break
143+
144+
145+
# Handle stdwin events until none are left
146+
#
147+
def stdwin_select_handler(*args):
148+
while 1:
149+
try:
150+
event = stdwinq.pollevent()
151+
except KeyboardInterrupt:
152+
event = (WE_COMMAND, None, WC_CANCEL)
153+
if event is None:
154+
break
155+
dispatch(event)
156+
157+
158+
# Run a modal dialog loop for a window. The dialog window must have
159+
# been registered first. This prohibits most events (except size/draw
160+
# events) to other windows. The modal dialog loop ends when the
161+
# dialog window unregisters itself.
162+
#
163+
passthrough = WE_SIZE, WE_DRAW
164+
beeping = WE_MOUSE_DOWN, WE_COMMAND, WE_CHAR, WE_KEY, WE_CLOSE, WE_MENU
165+
#
166+
def modaldialog(window):
167+
if window not in windows:
168+
raise ValueError, 'modaldialog window not registered'
169+
while window in windows:
61170
try:
62-
dispatch(stdwinq.getevent())
171+
event = stdwinq.getevent()
63172
except KeyboardInterrupt:
64-
dispatch(WE_COMMAND, stdwin.getactive(), WC_CANCEL)
173+
event = WE_COMMAND, None, WC_CANCEL
174+
etype, ewindow, edetail = event
175+
if etype not in passthrough and ewindow <> window:
176+
if etype in beeping:
177+
stdwin.fleep()
178+
continue
179+
dispatch(event)
65180

66181

67182
# Dispatch a single event.
183+
# Events for the no window in particular are sent to the active window
184+
# or to the last window that received an event (these hacks are for the
185+
# WE_LOST_SEL event, which is directed to no particular window).
68186
# Windows not in the windows list don't get their events:
69187
# events for such windows are silently ignored.
70188
#
71189
def dispatch(event):
72-
if event[1] in windows:
73-
event[1].dispatch(event)
190+
global last_window
191+
if event[1] == None:
192+
active = stdwin.getactive()
193+
if active: last_window = active
194+
else:
195+
last_window = event[1]
196+
if last_window in windows:
197+
last_window.dispatch(event)
198+
199+
200+
# Dialog base class
201+
#
202+
class Dialog:
203+
#
204+
def init(self, title):
205+
self.window = stdwin.open(title)
206+
self.window.dispatch = self.dispatch
207+
register(self.window)
208+
return self
209+
#
210+
def close(self):
211+
unregister(self.window)
212+
del self.window.dispatch
213+
self.window.close()
214+
#
215+
def dispatch(self, event):
216+
etype, ewindow, edetail = event
217+
if etype == WE_CLOSE:
218+
self.close()
219+
220+
221+
# Standard modal dialogs
222+
# XXX implemented using stdwin dialogs for now
223+
#
224+
def askstr(prompt, default):
225+
return stdwin.askstr(prompt, default)
226+
#
227+
def askync(prompt, yesorno):
228+
return stdwin.askync(prompt, yesorno)
229+
#
230+
def askfile(prompt, default, new):
231+
return stdwin.askfile(prompt, default, new)
232+
#
233+
def message(msg):
234+
stdwin.message(msg)

Lib/lib-stdwin/stdwinevents.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,18 @@
4444
WS_CLIPBOARD = 0
4545
WS_PRIMARY = 1
4646
WS_SECONDARY = 2
47+
48+
# Modifier masks in key and mouse events
49+
50+
WM_SHIFT = (1 << 0)
51+
WM_LOCK = (1 << 1)
52+
WM_CONTROL = (1 << 2)
53+
WM_META = (1 << 3)
54+
WM_OPTION = (1 << 4)
55+
WM_NUM = (1 << 5)
56+
57+
WM_BUTTON1 = (1 << 8)
58+
WM_BUTTON2 = (1 << 9)
59+
WM_BUTTON3 = (1 << 10)
60+
WM_BUTTON4 = (1 << 11)
61+
WM_BUTTON5 = (1 << 12)

Lib/nntplib.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
# Example:
66
#
7-
# >>> from nntp import NNTP
7+
# >>> from nntplib import NNTP
88
# >>> s = NNTP().init('charon')
99
# >>> resp, count, first, last, name = s.group('nlnet.misc')
1010
# >>> print 'Group', name, 'has', count, 'articles, range', first, 'to', last
@@ -32,12 +32,12 @@
3232
import string
3333

3434

35-
# Exception raiseds when an error or invalid response is received
35+
# Exception raised when an error or invalid response is received
3636

37-
error_reply = 'nntp.error_reply' # unexpected [123]xx reply
38-
error_function = 'nntp.error_function' # 4xx errors
39-
error_form = 'nntp.error_form' # 5xx errors
40-
error_protocol = 'nntp.error_protocol' # response does not begin with [1-5]
37+
error_reply = 'nntplib.error_reply' # unexpected [123]xx reply
38+
error_temp = 'nntplib.error_temp' # 4xx errors
39+
error_perm = 'nntplib.error_perm' # 5xx errors
40+
error_proto = 'nntplib.error_proto' # response does not begin with [1-5]
4141

4242

4343
# Standard port used by NNTP servers
@@ -119,11 +119,11 @@ def getresp(self):
119119
if self.debugging: print '*resp*', `resp`
120120
c = resp[:1]
121121
if c == '4':
122-
raise error_function, resp
122+
raise error_temp, resp
123123
if c == '5':
124-
raise error_form, resp
124+
raise error_perm, resp
125125
if c not in '123':
126-
raise error_protocol, resp
126+
raise error_proto, resp
127127
return resp
128128

129129
# Internal: get a response plus following text from the server.
@@ -342,7 +342,7 @@ def post(self, f):
342342

343343
def ihave(self, id, f):
344344
resp = self.shortcmd('IHAVE ' + id)
345-
# Raises error_function if the server already has it
345+
# Raises error_??? if the server already has it
346346
if resp[0] <> '3':
347347
raise error_reply, resp
348348
while 1:

0 commit comments

Comments
 (0)