Fix three PyChecker-detected gotchas.
[python/dscho.git] / Mac / Demo / waste / htmled.py
blob764394747417515071b6c77431832c8810c57f24
1 # A minimal text editor.
3 # To be done:
4 # - Functionality: find, etc.
6 from Menu import DrawMenuBar
7 from FrameWork import *
8 import Win
9 import Qd
10 import Res
11 import Fm
12 import waste
13 import WASTEconst
14 import Scrap
15 import os
16 import macfs
17 import MACFS
18 import regsub
19 import string
20 import htmllib
22 WATCH = Qd.GetCursor(4).data
24 LEFTMARGIN=0
26 UNDOLABELS = [ # Indexed by WEGetUndoInfo() value
27 None, "", "typing", "Cut", "Paste", "Clear", "Drag", "Style"]
29 # Style and size menu. Note that style order is important (tied to bit values)
30 STYLES = [
31 ("Bold", "B"), ("Italic", "I"), ("Underline", "U"), ("Outline", "O"),
32 ("Shadow", ""), ("Condensed", ""), ("Extended", "")
34 SIZES = [ 9, 10, 12, 14, 18, 24]
36 # Sizes for HTML tag types
37 HTML_SIZE={
38 'h1': 18,
39 'h2': 14
42 BIGREGION=Qd.NewRgn()
43 Qd.SetRectRgn(BIGREGION, -16000, -16000, 16000, 16000)
45 class WasteWindow(ScrolledWindow):
46 def open(self, path, name, data):
47 self.path = path
48 self.name = name
49 r = windowbounds(400, 400)
50 w = Win.NewWindow(r, name, 1, 0, -1, 1, 0x55555555)
51 self.wid = w
52 vr = LEFTMARGIN, 0, r[2]-r[0]-15, r[3]-r[1]-15
53 dr = (0, 0, vr[2], 0)
54 Qd.SetPort(w)
55 Qd.TextFont(4)
56 Qd.TextSize(9)
57 flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoOutlineHilite | \
58 WASTEconst.weDoMonoStyled | WASTEconst.weDoUndo
59 self.ted = waste.WENew(dr, vr, flags)
60 self.ted.WEInstallTabHooks()
61 style, soup = self.getstylesoup(self.path)
62 self.ted.WEInsert(data, style, soup)
63 self.ted.WESetSelection(0,0)
64 self.ted.WECalText()
65 self.ted.WEResetModCount()
66 w.DrawGrowIcon()
67 self.scrollbars()
68 self.do_postopen()
69 self.do_activate(1, None)
71 def getstylesoup(self, pathname):
72 if not pathname:
73 return None, None
74 oldrf = Res.CurResFile()
75 try:
76 rf = Res.FSpOpenResFile(self.path, 1)
77 except Res.Error:
78 return None, None
79 try:
80 hstyle = Res.Get1Resource('styl', 128)
81 hstyle.DetachResource()
82 except Res.Error:
83 hstyle = None
84 try:
85 hsoup = Res.Get1Resource('SOUP', 128)
86 hsoup.DetachResource()
87 except Res.Error:
88 hsoup = None
89 Res.CloseResFile(rf)
90 Res.UseResFile(oldrf)
91 return hstyle, hsoup
93 def do_idle(self, event):
94 (what, message, when, where, modifiers) = event
95 Qd.SetPort(self.wid)
96 self.ted.WEIdle()
97 if self.ted.WEAdjustCursor(where, BIGREGION):
98 return
99 Qd.SetCursor(Qd.qd.arrow)
101 def getscrollbarvalues(self):
102 dr = self.ted.WEGetDestRect()
103 vr = self.ted.WEGetViewRect()
104 vx = self.scalebarvalue(dr[0], dr[2], vr[0], vr[2])
105 vy = self.scalebarvalue(dr[1], dr[3], vr[1], vr[3])
106 return vx, vy
108 def scrollbar_callback(self, which, what, value):
109 if which == 'y':
111 # "line" size is minimum of top and bottom line size
113 topline_off,dummy = self.ted.WEGetOffset((1,1))
114 topline_num = self.ted.WEOffsetToLine(topline_off)
115 toplineheight = self.ted.WEGetHeight(topline_num, topline_num+1)
117 botlinepos = self.ted.WEGetViewRect()[3]
118 botline_off, dummy = self.ted.WEGetOffset((1, botlinepos-1))
119 botline_num = self.ted.WEOffsetToLine(botline_off)
120 botlineheight = self.ted.WEGetHeight(botline_num, botline_num+1)
122 if botlineheight == 0:
123 botlineheight = self.ted.WEGetHeight(botline_num-1, botline_num)
124 if botlineheight < toplineheight:
125 lineheight = botlineheight
126 else:
127 lineheight = toplineheight
128 if lineheight <= 0:
129 lineheight = 1
131 # Now do the command.
133 if what == 'set':
134 height = self.ted.WEGetHeight(0, 0x3fffffff)
135 cur = self.getscrollbarvalues()[1]
136 delta = (cur-value)*height/32767
137 if what == '-':
138 delta = lineheight
139 elif what == '--':
140 delta = (self.ted.WEGetViewRect()[3]-lineheight)
141 if delta <= 0:
142 delta = lineheight
143 elif what == '+':
144 delta = -lineheight
145 elif what == '++':
146 delta = -(self.ted.WEGetViewRect()[3]-lineheight)
147 if delta >= 0:
148 delta = -lineheight
149 self.ted.WEScroll(0, delta)
150 else:
151 if what == 'set':
152 return # XXXX
153 vr = self.ted.WEGetViewRect()
154 winwidth = vr[2]-vr[0]
155 if what == '-':
156 delta = winwidth/10
157 elif what == '--':
158 delta = winwidth/2
159 elif what == '+':
160 delta = -winwidth/10
161 elif what == '++':
162 delta = -winwidth/2
163 self.ted.WEScroll(delta, 0)
164 # Pin the scroll
165 l, t, r, b = self.ted.WEGetDestRect()
166 vl, vt, vr, vb = self.ted.WEGetViewRect()
167 if t > 0 or l > 0:
168 dx = dy = 0
169 if t > 0: dy = -t
170 if l > 0: dx = -l
171 self.ted.WEScroll(dx, dy)
172 elif b < vb:
173 self.ted.WEScroll(0, vb-b)
176 def do_activate(self, onoff, evt):
177 Qd.SetPort(self.wid)
178 ScrolledWindow.do_activate(self, onoff, evt)
179 if onoff:
180 self.ted.WEActivate()
181 self.parent.active = self
182 self.parent.updatemenubar()
183 else:
184 self.ted.WEDeactivate()
186 def do_update(self, wid, event):
187 region = wid.GetWindowPort().visRgn
188 if Qd.EmptyRgn(region):
189 return
190 Qd.EraseRgn(region)
191 self.ted.WEUpdate(region)
192 self.updatescrollbars()
194 def do_postresize(self, width, height, window):
195 l, t, r, b = self.ted.WEGetViewRect()
196 vr = (l, t, l+width-15, t+height-15)
197 self.ted.WESetViewRect(vr)
198 self.wid.InvalWindowRect(vr)
199 ScrolledWindow.do_postresize(self, width, height, window)
201 def do_contentclick(self, local, modifiers, evt):
202 (what, message, when, where, modifiers) = evt
203 self.ted.WEClick(local, modifiers, when)
204 self.updatescrollbars()
205 self.parent.updatemenubar()
207 def do_char(self, ch, event):
208 self.ted.WESelView()
209 (what, message, when, where, modifiers) = event
210 self.ted.WEKey(ord(ch), modifiers)
211 self.updatescrollbars()
212 self.parent.updatemenubar()
214 def close(self):
215 if self.ted.WEGetModCount():
216 save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?'%self.name, 1)
217 if save > 0:
218 self.menu_save()
219 elif save < 0:
220 return
221 if self.parent.active == self:
222 self.parent.active = None
223 self.parent.updatemenubar()
224 del self.ted
225 self.do_postclose()
227 def menu_save(self):
228 if not self.path:
229 self.menu_save_as()
230 return # Will call us recursively
232 # First save data
234 dhandle = self.ted.WEGetText()
235 data = dhandle.data
236 fp = open(self.path, 'wb') # NOTE: wb, because data has CR for end-of-line
237 fp.write(data)
238 if data[-1] <> '\r': fp.write('\r')
239 fp.close()
241 # Now save style and soup
243 oldresfile = Res.CurResFile()
244 try:
245 rf = Res.FSpOpenResFile(self.path, 3)
246 except Res.Error:
247 Res.FSpCreateResFile(self.path, '????', 'TEXT', MACFS.smAllScripts)
248 rf = Res.FSpOpenResFile(self.path, 3)
249 styles = Res.Resource('')
250 soup = Res.Resource('')
251 self.ted.WECopyRange(0, 0x3fffffff, None, styles, soup)
252 styles.AddResource('styl', 128, '')
253 soup.AddResource('SOUP', 128, '')
254 Res.CloseResFile(rf)
255 Res.UseResFile(oldresfile)
257 self.ted.WEResetModCount()
259 def menu_save_as(self):
260 fss, ok = macfs.StandardPutFile('Save as:')
261 if not ok: return
262 self.path = fss.as_pathname()
263 self.name = os.path.split(self.path)[-1]
264 self.wid.SetWTitle(self.name)
265 self.menu_save()
267 def menu_insert(self, fp):
268 self.ted.WESelView()
269 data = fp.read()
270 self.ted.WEInsert(data, None, None)
271 self.updatescrollbars()
272 self.parent.updatemenubar()
274 def menu_insert_html(self, fp):
275 import htmllib
276 import formatter
277 f = formatter.AbstractFormatter(self)
279 # Remember where we are, and don't update
280 Qd.SetCursor(WATCH)
281 start, dummy = self.ted.WEGetSelection()
282 self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 1)
284 self.html_init()
285 p = MyHTMLParser(f)
286 p.feed(fp.read())
288 # Restore updating, recalc, set focus
289 dummy, end = self.ted.WEGetSelection()
290 self.ted.WECalText()
291 self.ted.WESetSelection(start, end)
292 self.ted.WESelView()
293 self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 0)
294 self.wid.InvalWindowRect(self.ted.WEGetViewRect())
296 self.updatescrollbars()
297 self.parent.updatemenubar()
299 def menu_cut(self):
300 self.ted.WESelView()
301 self.ted.WECut()
302 Scrap.ZeroScrap()
303 self.ted.WECut()
304 self.updatescrollbars()
305 self.parent.updatemenubar()
307 def menu_copy(self):
308 Scrap.ZeroScrap()
309 self.ted.WECopy()
310 self.updatescrollbars()
311 self.parent.updatemenubar()
313 def menu_paste(self):
314 self.ted.WESelView()
315 self.ted.WEPaste()
316 self.updatescrollbars()
317 self.parent.updatemenubar()
319 def menu_clear(self):
320 self.ted.WESelView()
321 self.ted.WEDelete()
322 self.updatescrollbars()
323 self.parent.updatemenubar()
325 def menu_undo(self):
326 self.ted.WEUndo()
327 self.updatescrollbars()
328 self.parent.updatemenubar()
330 def menu_setfont(self, font):
331 font = Fm.GetFNum(font)
332 self.mysetstyle(WASTEconst.weDoFont, (font, 0, 0, (0,0,0)))
333 self.parent.updatemenubar()
335 def menu_modface(self, face):
336 self.mysetstyle(WASTEconst.weDoFace|WASTEconst.weDoToggleFace,
337 (0, face, 0, (0,0,0)))
339 def menu_setface(self, face):
340 self.mysetstyle(WASTEconst.weDoFace|WASTEconst.weDoReplaceFace,
341 (0, face, 0, (0,0,0)))
343 def menu_setsize(self, size):
344 self.mysetstyle(WASTEconst.weDoSize, (0, 0, size, (0,0,0)))
346 def menu_incsize(self, size):
347 self.mysetstyle(WASTEconst.weDoAddSize, (0, 0, size, (0,0,0)))
349 def mysetstyle(self, which, how):
350 self.ted.WESelView()
351 self.ted.WESetStyle(which, how)
352 self.parent.updatemenubar()
354 def have_selection(self):
355 start, stop = self.ted.WEGetSelection()
356 return start < stop
358 def can_paste(self):
359 return self.ted.WECanPaste()
361 def can_undo(self):
362 which, redo = self.ted.WEGetUndoInfo()
363 which = UNDOLABELS[which]
364 if which == None: return None
365 if redo:
366 return "Redo "+which
367 else:
368 return "Undo "+which
370 def getruninfo(self):
371 all = (WASTEconst.weDoFont | WASTEconst.weDoFace | WASTEconst.weDoSize)
372 dummy, mode, (font, face, size, color) = self.ted.WEContinuousStyle(all)
373 if not (mode & WASTEconst.weDoFont):
374 font = None
375 else:
376 font = Fm.GetFontName(font)
377 if not (mode & WASTEconst.weDoFace): fact = None
378 if not (mode & WASTEconst.weDoSize): size = None
379 return font, face, size
382 # Methods for writer class for html formatter
385 def html_init(self):
386 self.html_font = [12, 0, 0, 0]
387 self.html_style = 0
388 self.html_color = (0,0,0)
389 self.new_font(self.html_font)
391 def new_font(self, font):
392 if font == None:
393 font = (12, 0, 0, 0)
394 font = map(lambda x:x, font)
395 for i in range(len(font)):
396 if font[i] == None:
397 font[i] = self.html_font[i]
398 [size, italic, bold, tt] = font
399 self.html_font = font[:]
400 if tt:
401 font = Fm.GetFNum('Courier')
402 else:
403 font = Fm.GetFNum('Times')
404 if HTML_SIZE.has_key(size):
405 size = HTML_SIZE[size]
406 else:
407 size = 12
408 face = 0
409 if bold: face = face | 1
410 if italic: face = face | 2
411 face = face | self.html_style
412 self.ted.WESetStyle(WASTEconst.weDoFont | WASTEconst.weDoFace |
413 WASTEconst.weDoSize | WASTEconst.weDoColor,
414 (font, face, size, self.html_color))
416 def new_margin(self, margin, level):
417 self.ted.WEInsert('[Margin %s %s]'%(margin, level), None, None)
419 def new_spacing(self, spacing):
420 self.ted.WEInsert('[spacing %s]'%spacing, None, None)
422 def new_styles(self, styles):
423 self.html_style = 0
424 self.html_color = (0,0,0)
425 if 'anchor' in styles:
426 self.html_style = self.html_style | 4
427 self.html_color = (0xffff, 0, 0)
428 self.new_font(self.html_font)
430 def send_paragraph(self, blankline):
431 self.ted.WEInsert('\r'*(blankline+1), None, None)
433 def send_line_break(self):
434 self.ted.WEInsert('\r', None, None)
436 def send_hor_rule(self, *args, **kw):
437 # Ignore ruler options, for now
438 dummydata = Res.Resource('')
439 self.ted.WEInsertObject('rulr', dummydata, (0,0))
441 def send_label_data(self, data):
442 self.ted.WEInsert(data, None, None)
444 def send_flowing_data(self, data):
445 self.ted.WEInsert(data, None, None)
447 def send_literal_data(self, data):
448 data = regsub.gsub('\n', '\r', data)
449 data = string.expandtabs(data)
450 self.ted.WEInsert(data, None, None)
452 class Wed(Application):
453 def __init__(self):
454 Application.__init__(self)
455 self.num = 0
456 self.active = None
457 self.updatemenubar()
458 waste.STDObjectHandlers()
459 # Handler for horizontal ruler
460 waste.WEInstallObjectHandler('rulr', 'new ', self.newRuler)
461 waste.WEInstallObjectHandler('rulr', 'draw', self.drawRuler)
463 def makeusermenus(self):
464 self.filemenu = m = Menu(self.menubar, "File")
465 self.newitem = MenuItem(m, "New window", "N", self.open)
466 self.openitem = MenuItem(m, "Open...", "O", self.openfile)
467 self.closeitem = MenuItem(m, "Close", "W", self.closewin)
468 m.addseparator()
469 self.saveitem = MenuItem(m, "Save", "S", self.save)
470 self.saveasitem = MenuItem(m, "Save as...", "", self.saveas)
471 m.addseparator()
472 self.insertitem = MenuItem(m, "Insert plaintext...", "", self.insertfile)
473 self.htmlitem = MenuItem(m, "Insert HTML...", "", self.inserthtml)
474 m.addseparator()
475 self.quititem = MenuItem(m, "Quit", "Q", self.quit)
477 self.editmenu = m = Menu(self.menubar, "Edit")
478 self.undoitem = MenuItem(m, "Undo", "Z", self.undo)
479 self.cutitem = MenuItem(m, "Cut", "X", self.cut)
480 self.copyitem = MenuItem(m, "Copy", "C", self.copy)
481 self.pasteitem = MenuItem(m, "Paste", "V", self.paste)
482 self.clearitem = MenuItem(m, "Clear", "", self.clear)
484 self.makefontmenu()
486 # Groups of items enabled together:
487 self.windowgroup = [self.closeitem, self.saveitem, self.saveasitem,
488 self.editmenu, self.fontmenu, self.facemenu, self.sizemenu,
489 self.insertitem]
490 self.focusgroup = [self.cutitem, self.copyitem, self.clearitem]
491 self.windowgroup_on = -1
492 self.focusgroup_on = -1
493 self.pastegroup_on = -1
494 self.undo_label = "never"
495 self.ffs_values = ()
497 def makefontmenu(self):
498 self.fontmenu = Menu(self.menubar, "Font")
499 self.fontnames = getfontnames()
500 self.fontitems = []
501 for n in self.fontnames:
502 m = MenuItem(self.fontmenu, n, "", self.selfont)
503 self.fontitems.append(m)
504 self.facemenu = Menu(self.menubar, "Style")
505 self.faceitems = []
506 for n, shortcut in STYLES:
507 m = MenuItem(self.facemenu, n, shortcut, self.selface)
508 self.faceitems.append(m)
509 self.facemenu.addseparator()
510 self.faceitem_normal = MenuItem(self.facemenu, "Normal", "N",
511 self.selfacenormal)
512 self.sizemenu = Menu(self.menubar, "Size")
513 self.sizeitems = []
514 for n in SIZES:
515 m = MenuItem(self.sizemenu, `n`, "", self.selsize)
516 self.sizeitems.append(m)
517 self.sizemenu.addseparator()
518 self.sizeitem_bigger = MenuItem(self.sizemenu, "Bigger", "+",
519 self.selsizebigger)
520 self.sizeitem_smaller = MenuItem(self.sizemenu, "Smaller", "-",
521 self.selsizesmaller)
523 def selfont(self, id, item, *rest):
524 if self.active:
525 font = self.fontnames[item-1]
526 self.active.menu_setfont(font)
527 else:
528 EasyDialogs.Message("No active window?")
530 def selface(self, id, item, *rest):
531 if self.active:
532 face = (1<<(item-1))
533 self.active.menu_modface(face)
534 else:
535 EasyDialogs.Message("No active window?")
537 def selfacenormal(self, *rest):
538 if self.active:
539 self.active.menu_setface(0)
540 else:
541 EasyDialogs.Message("No active window?")
543 def selsize(self, id, item, *rest):
544 if self.active:
545 size = SIZES[item-1]
546 self.active.menu_setsize(size)
547 else:
548 EasyDialogs.Message("No active window?")
550 def selsizebigger(self, *rest):
551 if self.active:
552 self.active.menu_incsize(2)
553 else:
554 EasyDialogs.Message("No active window?")
556 def selsizesmaller(self, *rest):
557 if self.active:
558 self.active.menu_incsize(-2)
559 else:
560 EasyDialogs.Message("No active window?")
562 def updatemenubar(self):
563 changed = 0
564 on = (self.active <> None)
565 if on <> self.windowgroup_on:
566 for m in self.windowgroup:
567 m.enable(on)
568 self.windowgroup_on = on
569 changed = 1
570 if on:
571 # only if we have an edit menu
572 on = self.active.have_selection()
573 if on <> self.focusgroup_on:
574 for m in self.focusgroup:
575 m.enable(on)
576 self.focusgroup_on = on
577 changed = 1
578 on = self.active.can_paste()
579 if on <> self.pastegroup_on:
580 self.pasteitem.enable(on)
581 self.pastegroup_on = on
582 changed = 1
583 on = self.active.can_undo()
584 if on <> self.undo_label:
585 if on:
586 self.undoitem.enable(1)
587 self.undoitem.settext(on)
588 self.undo_label = on
589 else:
590 self.undoitem.settext("Nothing to undo")
591 self.undoitem.enable(0)
592 changed = 1
593 if self.updatefontmenus():
594 changed = 1
595 if changed:
596 DrawMenuBar()
598 def updatefontmenus(self):
599 info = self.active.getruninfo()
600 if info == self.ffs_values:
601 return 0
602 # Remove old checkmarks
603 if self.ffs_values == ():
604 self.ffs_values = (None, None, None)
605 font, face, size = self.ffs_values
606 if font <> None:
607 fnum = self.fontnames.index(font)
608 self.fontitems[fnum].check(0)
609 if face <> None:
610 for i in range(len(self.faceitems)):
611 if face & (1<<i):
612 self.faceitems[i].check(0)
613 if size <> None:
614 for i in range(len(self.sizeitems)):
615 if SIZES[i] == size:
616 self.sizeitems[i].check(0)
618 self.ffs_values = info
619 # Set new checkmarks
620 font, face, size = self.ffs_values
621 if font <> None:
622 fnum = self.fontnames.index(font)
623 self.fontitems[fnum].check(1)
624 if face <> None:
625 for i in range(len(self.faceitems)):
626 if face & (1<<i):
627 self.faceitems[i].check(1)
628 if size <> None:
629 for i in range(len(self.sizeitems)):
630 if SIZES[i] == size:
631 self.sizeitems[i].check(1)
632 # Set outline/normal for sizes
633 if font:
634 exists = getfontsizes(font, SIZES)
635 for i in range(len(self.sizeitems)):
636 if exists[i]:
637 self.sizeitems[i].setstyle(0)
638 else:
639 self.sizeitems[i].setstyle(8)
642 # Apple menu
645 def do_about(self, id, item, window, event):
646 EasyDialogs.Message("A simple single-font text editor based on WASTE")
649 # File menu
652 def open(self, *args):
653 self._open(0)
655 def openfile(self, *args):
656 self._open(1)
658 def _open(self, askfile):
659 if askfile:
660 fss, ok = macfs.StandardGetFile('TEXT')
661 if not ok:
662 return
663 path = fss.as_pathname()
664 name = os.path.split(path)[-1]
665 try:
666 fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
667 data = fp.read()
668 fp.close()
669 except IOError, arg:
670 EasyDialogs.Message("IOERROR: "+`arg`)
671 return
672 else:
673 path = None
674 name = "Untitled %d"%self.num
675 data = ''
676 w = WasteWindow(self)
677 w.open(path, name, data)
678 self.num = self.num + 1
680 def insertfile(self, *args):
681 if self.active:
682 fss, ok = macfs.StandardGetFile('TEXT')
683 if not ok:
684 return
685 path = fss.as_pathname()
686 try:
687 fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
688 except IOError, arg:
689 EasyDialogs.Message("IOERROR: "+`arg`)
690 return
691 self.active.menu_insert(fp)
692 else:
693 EasyDialogs.Message("No active window?")
695 def inserthtml(self, *args):
696 if self.active:
697 fss, ok = macfs.StandardGetFile('TEXT')
698 if not ok:
699 return
700 path = fss.as_pathname()
701 try:
702 fp = open(path, 'r')
703 except IOError, arg:
704 EasyDialogs.Message("IOERROR: "+`arg`)
705 return
706 self.active.menu_insert_html(fp)
707 else:
708 EasyDialogs.Message("No active window?")
711 def closewin(self, *args):
712 if self.active:
713 self.active.close()
714 else:
715 EasyDialogs.Message("No active window?")
717 def save(self, *args):
718 if self.active:
719 self.active.menu_save()
720 else:
721 EasyDialogs.Message("No active window?")
723 def saveas(self, *args):
724 if self.active:
725 self.active.menu_save_as()
726 else:
727 EasyDialogs.Message("No active window?")
730 def quit(self, *args):
731 for w in self._windows.values():
732 w.close()
733 if self._windows:
734 return
735 self._quit()
738 # Edit menu
741 def undo(self, *args):
742 if self.active:
743 self.active.menu_undo()
744 else:
745 EasyDialogs.Message("No active window?")
747 def cut(self, *args):
748 if self.active:
749 self.active.menu_cut()
750 else:
751 EasyDialogs.Message("No active window?")
753 def copy(self, *args):
754 if self.active:
755 self.active.menu_copy()
756 else:
757 EasyDialogs.Message("No active window?")
759 def paste(self, *args):
760 if self.active:
761 self.active.menu_paste()
762 else:
763 EasyDialogs.Message("No active window?")
765 def clear(self, *args):
766 if self.active:
767 self.active.menu_clear()
768 else:
769 EasyDialogs.Message("No active window?")
772 # Other stuff
775 def idle(self, event):
776 if self.active:
777 self.active.do_idle(event)
779 def newRuler(self, obj):
780 """Insert a new ruler. Make it as wide as the window minus 2 pxls"""
781 ted = obj.WEGetObjectOwner()
782 l, t, r, b = ted.WEGetDestRect()
783 return r-l, 4
785 def drawRuler(self, (l, t, r, b), obj):
786 y = (t+b)/2
787 Qd.MoveTo(l+2, y)
788 Qd.LineTo(r-2, y)
789 return 0
791 class MyHTMLParser(htmllib.HTMLParser):
793 def anchor_bgn(self, href, name, type):
794 self.anchor = href
795 if self.anchor:
796 self.anchorlist.append(href)
797 self.formatter.push_style('anchor')
799 def anchor_end(self):
800 if self.anchor:
801 self.anchor = None
802 self.formatter.pop_style()
805 def getfontnames():
806 names = []
807 for i in range(256):
808 n = Fm.GetFontName(i)
809 if n: names.append(n)
810 return names
812 def getfontsizes(name, sizes):
813 exist = []
814 num = Fm.GetFNum(name)
815 for sz in sizes:
816 if Fm.RealFont(num, sz):
817 exist.append(1)
818 else:
819 exist.append(0)
820 return exist
822 def main():
823 App = Wed()
824 App.mainloop()
826 if __name__ == '__main__':
827 main()