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