File: DocWriter.py

package info (click to toggle)
palm-doctoolkit 0.99.1-2
  • links: PTS
  • area: main
  • in suites: slink
  • size: 152 kB
  • ctags: 130
  • sloc: python: 657; makefile: 40; sh: 19
file content (249 lines) | stat: -rw-r--r-- 7,576 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
"""
  DocWriter.py - DocWriter class and friends
  $Id: DocWriter.py,v 1.2 1998/09/04 08:36:46 rob Exp $

  Copyright 1998 Rob Tillotson <rob@io.com>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License, version 2,
  as published by the Free Software Foundation.

  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write the Free Software Foundation,
  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.


  This module implements a Writer class which outputs to an e-text.
  It is suitable for use with the regular AbstractFormatter object.
  This writer has a couple of extra methods, for opening a document,
  setting bookmarks, etc.
  
"""
__version__ = '$Id: DocWriter.py,v 1.2 1998/09/04 08:36:46 rob Exp $'

import sys, string, os

import formatter

import metrics

from PDA.Palm.App import Doc

DOCTYPES = ['aportis', 'teal']

DEFAULT_DOCTYPE = 'aportis'

teal_header_attrs = {
    1: {'FONT': '2', 'ALIGN': 'CENTER', 'STYLE': 'NORMAL'},
    2: {'FONT': '1', 'ALIGN': 'LEFT', 'STYLE': 'UNDERLINE'},
    3: {'FONT': '1', 'ALIGN': 'LEFT', 'STYLE': 'NORMAL'},
    4: {'FONT': '0', 'ALIGN': 'LEFT', 'STYLE': 'UNDERLINE'},
    5: {'FONT': '0', 'ALIGN': 'LEFT', 'STYLE': 'UNDERLINE'},
    6: {'FONT': '0', 'ALIGN': 'LEFT', 'STYLE': 'UNDERLINE'}
    }
teal_header_fonts = {
    1: 2,
    2: 1,
    3: 1
    }
teal_default_header_attrs = {'FONT': '0', 'ALIGN': 'LEFT', 'STYLE': 'NORMAL'}

def tag(name, attr):
    s = '<'+name
    if attr:
	s = s + ' ' + string.join(map(lambda x: '%s=%s' % x, attr.items()))
    s = s + '>'
    return s

class DevNull:
    def write(self, *a, **kw): pass
    def read(self, *a, **kw): return ''
    def readline(self, *a, **kw): return ''
    def readlines(self, *a, **kw): return []
    def close(self, *a, **kw): pass
    
class DocWriter(formatter.NullWriter):
    """A Writer which outputs to a Doc-format e-text, via PalmPython.
    """
    def __init__(self, target=None, title=None, options=None):
	formatter.NullWriter.__init__(self)
	self.options = {}
	if options: self.options.update(options)
	if target:
	    self.open(target, title)
	elif title:
	    self.open_stdout()
	else:
	    self.doc = DevNull()
	self.reset()

    def has_option(self, k): return self.options.has_key(k)
    def set_option(self, k, v=1): self.options[k] = v
    def get_option(self, k, d=None): return self.options.get(k,d)
    def clear_option(self, k):
	if self.options.has_key(k):
	    del self.options[k]
	    
    def open_stdout(self, target=None, title=None):
	"""Open the writer, sending output to stdout.  Use only for
	debugging, and note that some information (notably bookmarks)
	will not be passed along to the output, as it is effectively
	'out of band'.
	"""
	self.doc = sys.stdout
	
    def open(self, target, title, dlp=None):
	"""Open the document.  The first argument is the local filename,
	the second is the PalmOS database name.  If a third argument is
	provided, it must be an open DLP object to which the document is
	directly installed.
	"""
	kw = {}
	if self.options.has_key('creator'):
	    kw['creator'] = self.options['creator']
	if self.options.has_key('type'):
	    kw['type'] = self.options['type']
	if self.options.has_key('backup'):
	    kw['backup'] = self.options['backup']
	if self.options.has_key('category'):
	    kw['category'] = self.options['category']

	self.doc = apply(Doc.DOCWriter, (title, target), kw)

    def close(self):
	"""Close the document.
	"""
	self.flush()
	self.doc.close()
	self.doc = DevNull()

    def set_bookmark(self, s):
	"""Set a bookmark at the current output position; the single
	argument is the bookmark title.  (Per the Doc format, only
	the first 15 characters will be preserved; also, note that
	bookmarks appear in the menu in the order they are set.)
	"""
	if self.has_option('teal-bookmarks'):
	    self.send_raw_tag('BOOKMARK',{'NAME':'"%s"' % s[:15]})
	else:
	    self.flush()
	    self.doc.bookmark(s)

    def send_raw_tag(self, tagname, attr):
	"""Insert a raw SGML-like tag in the output, given the tag
	name and attributes.  Use this for inserting TealDoc-style
	images, rules, etc.
	"""
	self.flush()
	self.doc.write(tag(tagname, attr))

    def send_heading(self, text, level=1):
	"""Insert a heading of the specified level."""
	if self.has_option('teal-headers'):
	    if self.has_option('teal-wrap-headers'):
		l = metrics.wordwrap(text, max_width=160,
				     font=teal_header_fonts.get(level,0))
	    else:
		l = [text]
	    for t in l:
		d = {'TEXT': '"%s"' % t}
		d.update(teal_header_attrs.get(level, teal_default_header_attrs))
		self.send_raw_tag('HEADER', d)
		self.send_line_break()
	else:
	    self.send_literal_data(text)
	    self.send_line_break()
	    
    
    def set_title(self, title):
	"""Set the document title."""
	self.doc.title = title

    def has_title(self):
	if self.doc.title: return 1

    # --- writer API
    def reset(self):
	self.list_depth = 0

    def send_paragraph(self, blankline=0):
	"""Insert a paragraph break; the parameter (if present) is
	the number of blank lines to insert between this and the
	next paragraph.
	"""
	self.doc.write('\n'*blankline)
	# reset paragraph counters

    def send_line_break(self):
	"""Insert a line break."""
	self.doc.write('\n')
	# reset line counters

    def send_hor_rule(self, *a, **kw):
	"""Generate a horizontal rule.  If the output document is
	in Teal format, this method inserts a <HRULE> tag, and the
	keyword parameters are the attributes of that tag.  If the
	output is in standard Doc format, an artificial rule will
	be created by lining up a bunch of punctuation characters;
	the character type is specified by the 'char' attribute
	('*' is the default), and the count is estimated according
	to the width of the Pilot screen.
	"""
	if self.has_option('teal-hrules'):
	    if kw.has_key('char'): del kw['char']
	    if kw.has_key('break'): del kw['break']
	    # later, do various default things based on 'char'
	    self.doc.write(tag('HRULE', kw)+'\n')
	else:
	    char = kw.get('char', '*')[:1]
	    if char == '-': count = 39
	    else: count = 26
	    brk = kw.get('break', 'none')

	    if brk in ['before', 'both']: self.doc.write('\n')
	    self.doc.write(char * count)
	    if brk in ['after', 'both']: self.doc.write('\n')

    def send_literal_data(self, data):
	"""Send literal data to the document."""
	self.doc.write(data)

    def send_flowing_data(self, data):
	"""Send flowing data to the document."""
	self.doc.write(data)

    def send_label_data(self, data):
	self.doc.write('  '*self.list_depth)
	self.doc.write(data)
	if data and data[-1] not in ' \n\r\t':
	    self.doc.write(' ')
	
    #----
    def new_alignment(self, align):
	"""Does nothing, as the Doc format doesn't support it yet."""
	pass

    def new_font(self, font):
	"""Does nothing, as the Doc format doesn't support it yet."""
	pass

    def new_margin(self, margin, level):
	if margin is None or level == 0:
	    self.list_depth = 0
	elif margin in ['ol', 'ul']:
	    self.list_depth = level - 1

    def new_spacing(self, spacing):
	"""Does nothing, as the Doc format doesn't support it yet."""
	pass

    def new_styles(self, styles):
	"""Does nothing, as the Doc format doesn't support it yet."""
	pass