seawolf2357 commited on
Commit
d94b56e
·
verified ·
1 Parent(s): f711302
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. src/README.rst +6 -0
  2. src/hwp5/COPYING +661 -0
  3. src/hwp5/README +73 -0
  4. src/hwp5/VERSION.txt +1 -0
  5. src/hwp5/__init__.py +26 -0
  6. src/hwp5/binmodel/__init__.py +549 -0
  7. src/hwp5/binmodel/_shared.py +265 -0
  8. src/hwp5/binmodel/controlchar.py +215 -0
  9. src/hwp5/binmodel/controls/__init__.py +94 -0
  10. src/hwp5/binmodel/controls/_shared.py +59 -0
  11. src/hwp5/binmodel/controls/bookmark_control.py +50 -0
  12. src/hwp5/binmodel/controls/columns_def.py +84 -0
  13. src/hwp5/binmodel/controls/common_controls.py +81 -0
  14. src/hwp5/binmodel/controls/dutmal.py +48 -0
  15. src/hwp5/binmodel/controls/field.py +185 -0
  16. src/hwp5/binmodel/controls/gshape_object_control.py +28 -0
  17. src/hwp5/binmodel/controls/header_footer.py +48 -0
  18. src/hwp5/binmodel/controls/hidden_comment.py +34 -0
  19. src/hwp5/binmodel/controls/index_marker.py +37 -0
  20. src/hwp5/binmodel/controls/note.py +47 -0
  21. src/hwp5/binmodel/controls/numbering.py +69 -0
  22. src/hwp5/binmodel/controls/page_hide.py +42 -0
  23. src/hwp5/binmodel/controls/page_number_position.py +49 -0
  24. src/hwp5/binmodel/controls/page_odd_even.py +39 -0
  25. src/hwp5/binmodel/controls/section_def.py +73 -0
  26. src/hwp5/binmodel/controls/table_control.py +36 -0
  27. src/hwp5/binmodel/controls/tcps_control.py +38 -0
  28. src/hwp5/binmodel/tagid16_document_properties.py +47 -0
  29. src/hwp5/binmodel/tagid17_id_mappings.py +60 -0
  30. src/hwp5/binmodel/tagid18_bin_data.py +77 -0
  31. src/hwp5/binmodel/tagid19_face_name.py +136 -0
  32. src/hwp5/binmodel/tagid20_border_fill.py +89 -0
  33. src/hwp5/binmodel/tagid21_char_shape.py +90 -0
  34. src/hwp5/binmodel/tagid22_tab_def.py +60 -0
  35. src/hwp5/binmodel/tagid23_numbering.py +72 -0
  36. src/hwp5/binmodel/tagid24_bullet.py +52 -0
  37. src/hwp5/binmodel/tagid25_para_shape.py +97 -0
  38. src/hwp5/binmodel/tagid26_style.py +55 -0
  39. src/hwp5/binmodel/tagid27_doc_data.py +31 -0
  40. src/hwp5/binmodel/tagid28_distribute_doc_data.py +29 -0
  41. src/hwp5/binmodel/tagid30_compatible_document.py +42 -0
  42. src/hwp5/binmodel/tagid31_layout_compatibility.py +39 -0
  43. src/hwp5/binmodel/tagid32_unknown.py +29 -0
  44. src/hwp5/binmodel/tagid50_para_header.py +61 -0
  45. src/hwp5/binmodel/tagid51_para_text.py +61 -0
  46. src/hwp5/binmodel/tagid52_para_char_shape.py +64 -0
  47. src/hwp5/binmodel/tagid53_para_line_seg.py +95 -0
  48. src/hwp5/binmodel/tagid54_para_range_tag.py +54 -0
  49. src/hwp5/binmodel/tagid55_ctrl_header.py +44 -0
  50. src/hwp5/binmodel/tagid56_list_header.py +157 -0
src/README.rst ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ ``pyhwp/`` - the main source code
2
+ ---------------------------------
3
+
4
+ ``hwp5/``
5
+ The main source package. For now, there is not much documentation about the
6
+ source code.
src/hwp5/COPYING ADDED
@@ -0,0 +1,661 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU AFFERO GENERAL PUBLIC LICENSE
2
+ Version 3, 19 November 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU Affero General Public License is a free, copyleft license for
11
+ software and other kinds of works, specifically designed to ensure
12
+ cooperation with the community in the case of network server software.
13
+
14
+ The licenses for most software and other practical works are designed
15
+ to take away your freedom to share and change the works. By contrast,
16
+ our General Public Licenses are intended to guarantee your freedom to
17
+ share and change all versions of a program--to make sure it remains free
18
+ software for all its users.
19
+
20
+ When we speak of free software, we are referring to freedom, not
21
+ price. Our General Public Licenses are designed to make sure that you
22
+ have the freedom to distribute copies of free software (and charge for
23
+ them if you wish), that you receive source code or can get it if you
24
+ want it, that you can change the software or use pieces of it in new
25
+ free programs, and that you know you can do these things.
26
+
27
+ Developers that use our General Public Licenses protect your rights
28
+ with two steps: (1) assert copyright on the software, and (2) offer
29
+ you this License which gives you legal permission to copy, distribute
30
+ and/or modify the software.
31
+
32
+ A secondary benefit of defending all users' freedom is that
33
+ improvements made in alternate versions of the program, if they
34
+ receive widespread use, become available for other developers to
35
+ incorporate. Many developers of free software are heartened and
36
+ encouraged by the resulting cooperation. However, in the case of
37
+ software used on network servers, this result may fail to come about.
38
+ The GNU General Public License permits making a modified version and
39
+ letting the public access it on a server without ever releasing its
40
+ source code to the public.
41
+
42
+ The GNU Affero General Public License is designed specifically to
43
+ ensure that, in such cases, the modified source code becomes available
44
+ to the community. It requires the operator of a network server to
45
+ provide the source code of the modified version running there to the
46
+ users of that server. Therefore, public use of a modified version, on
47
+ a publicly accessible server, gives the public access to the source
48
+ code of the modified version.
49
+
50
+ An older license, called the Affero General Public License and
51
+ published by Affero, was designed to accomplish similar goals. This is
52
+ a different license, not a version of the Affero GPL, but Affero has
53
+ released a new version of the Affero GPL which permits relicensing under
54
+ this license.
55
+
56
+ The precise terms and conditions for copying, distribution and
57
+ modification follow.
58
+
59
+ TERMS AND CONDITIONS
60
+
61
+ 0. Definitions.
62
+
63
+ "This License" refers to version 3 of the GNU Affero General Public License.
64
+
65
+ "Copyright" also means copyright-like laws that apply to other kinds of
66
+ works, such as semiconductor masks.
67
+
68
+ "The Program" refers to any copyrightable work licensed under this
69
+ License. Each licensee is addressed as "you". "Licensees" and
70
+ "recipients" may be individuals or organizations.
71
+
72
+ To "modify" a work means to copy from or adapt all or part of the work
73
+ in a fashion requiring copyright permission, other than the making of an
74
+ exact copy. The resulting work is called a "modified version" of the
75
+ earlier work or a work "based on" the earlier work.
76
+
77
+ A "covered work" means either the unmodified Program or a work based
78
+ on the Program.
79
+
80
+ To "propagate" a work means to do anything with it that, without
81
+ permission, would make you directly or secondarily liable for
82
+ infringement under applicable copyright law, except executing it on a
83
+ computer or modifying a private copy. Propagation includes copying,
84
+ distribution (with or without modification), making available to the
85
+ public, and in some countries other activities as well.
86
+
87
+ To "convey" a work means any kind of propagation that enables other
88
+ parties to make or receive copies. Mere interaction with a user through
89
+ a computer network, with no transfer of a copy, is not conveying.
90
+
91
+ An interactive user interface displays "Appropriate Legal Notices"
92
+ to the extent that it includes a convenient and prominently visible
93
+ feature that (1) displays an appropriate copyright notice, and (2)
94
+ tells the user that there is no warranty for the work (except to the
95
+ extent that warranties are provided), that licensees may convey the
96
+ work under this License, and how to view a copy of this License. If
97
+ the interface presents a list of user commands or options, such as a
98
+ menu, a prominent item in the list meets this criterion.
99
+
100
+ 1. Source Code.
101
+
102
+ The "source code" for a work means the preferred form of the work
103
+ for making modifications to it. "Object code" means any non-source
104
+ form of a work.
105
+
106
+ A "Standard Interface" means an interface that either is an official
107
+ standard defined by a recognized standards body, or, in the case of
108
+ interfaces specified for a particular programming language, one that
109
+ is widely used among developers working in that language.
110
+
111
+ The "System Libraries" of an executable work include anything, other
112
+ than the work as a whole, that (a) is included in the normal form of
113
+ packaging a Major Component, but which is not part of that Major
114
+ Component, and (b) serves only to enable use of the work with that
115
+ Major Component, or to implement a Standard Interface for which an
116
+ implementation is available to the public in source code form. A
117
+ "Major Component", in this context, means a major essential component
118
+ (kernel, window system, and so on) of the specific operating system
119
+ (if any) on which the executable work runs, or a compiler used to
120
+ produce the work, or an object code interpreter used to run it.
121
+
122
+ The "Corresponding Source" for a work in object code form means all
123
+ the source code needed to generate, install, and (for an executable
124
+ work) run the object code and to modify the work, including scripts to
125
+ control those activities. However, it does not include the work's
126
+ System Libraries, or general-purpose tools or generally available free
127
+ programs which are used unmodified in performing those activities but
128
+ which are not part of the work. For example, Corresponding Source
129
+ includes interface definition files associated with source files for
130
+ the work, and the source code for shared libraries and dynamically
131
+ linked subprograms that the work is specifically designed to require,
132
+ such as by intimate data communication or control flow between those
133
+ subprograms and other parts of the work.
134
+
135
+ The Corresponding Source need not include anything that users
136
+ can regenerate automatically from other parts of the Corresponding
137
+ Source.
138
+
139
+ The Corresponding Source for a work in source code form is that
140
+ same work.
141
+
142
+ 2. Basic Permissions.
143
+
144
+ All rights granted under this License are granted for the term of
145
+ copyright on the Program, and are irrevocable provided the stated
146
+ conditions are met. This License explicitly affirms your unlimited
147
+ permission to run the unmodified Program. The output from running a
148
+ covered work is covered by this License only if the output, given its
149
+ content, constitutes a covered work. This License acknowledges your
150
+ rights of fair use or other equivalent, as provided by copyright law.
151
+
152
+ You may make, run and propagate covered works that you do not
153
+ convey, without conditions so long as your license otherwise remains
154
+ in force. You may convey covered works to others for the sole purpose
155
+ of having them make modifications exclusively for you, or provide you
156
+ with facilities for running those works, provided that you comply with
157
+ the terms of this License in conveying all material for which you do
158
+ not control copyright. Those thus making or running the covered works
159
+ for you must do so exclusively on your behalf, under your direction
160
+ and control, on terms that prohibit them from making any copies of
161
+ your copyrighted material outside their relationship with you.
162
+
163
+ Conveying under any other circumstances is permitted solely under
164
+ the conditions stated below. Sublicensing is not allowed; section 10
165
+ makes it unnecessary.
166
+
167
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168
+
169
+ No covered work shall be deemed part of an effective technological
170
+ measure under any applicable law fulfilling obligations under article
171
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
172
+ similar laws prohibiting or restricting circumvention of such
173
+ measures.
174
+
175
+ When you convey a covered work, you waive any legal power to forbid
176
+ circumvention of technological measures to the extent such circumvention
177
+ is effected by exercising rights under this License with respect to
178
+ the covered work, and you disclaim any intention to limit operation or
179
+ modification of the work as a means of enforcing, against the work's
180
+ users, your or third parties' legal rights to forbid circumvention of
181
+ technological measures.
182
+
183
+ 4. Conveying Verbatim Copies.
184
+
185
+ You may convey verbatim copies of the Program's source code as you
186
+ receive it, in any medium, provided that you conspicuously and
187
+ appropriately publish on each copy an appropriate copyright notice;
188
+ keep intact all notices stating that this License and any
189
+ non-permissive terms added in accord with section 7 apply to the code;
190
+ keep intact all notices of the absence of any warranty; and give all
191
+ recipients a copy of this License along with the Program.
192
+
193
+ You may charge any price or no price for each copy that you convey,
194
+ and you may offer support or warranty protection for a fee.
195
+
196
+ 5. Conveying Modified Source Versions.
197
+
198
+ You may convey a work based on the Program, or the modifications to
199
+ produce it from the Program, in the form of source code under the
200
+ terms of section 4, provided that you also meet all of these conditions:
201
+
202
+ a) The work must carry prominent notices stating that you modified
203
+ it, and giving a relevant date.
204
+
205
+ b) The work must carry prominent notices stating that it is
206
+ released under this License and any conditions added under section
207
+ 7. This requirement modifies the requirement in section 4 to
208
+ "keep intact all notices".
209
+
210
+ c) You must license the entire work, as a whole, under this
211
+ License to anyone who comes into possession of a copy. This
212
+ License will therefore apply, along with any applicable section 7
213
+ additional terms, to the whole of the work, and all its parts,
214
+ regardless of how they are packaged. This License gives no
215
+ permission to license the work in any other way, but it does not
216
+ invalidate such permission if you have separately received it.
217
+
218
+ d) If the work has interactive user interfaces, each must display
219
+ Appropriate Legal Notices; however, if the Program has interactive
220
+ interfaces that do not display Appropriate Legal Notices, your
221
+ work need not make them do so.
222
+
223
+ A compilation of a covered work with other separate and independent
224
+ works, which are not by their nature extensions of the covered work,
225
+ and which are not combined with it such as to form a larger program,
226
+ in or on a volume of a storage or distribution medium, is called an
227
+ "aggregate" if the compilation and its resulting copyright are not
228
+ used to limit the access or legal rights of the compilation's users
229
+ beyond what the individual works permit. Inclusion of a covered work
230
+ in an aggregate does not cause this License to apply to the other
231
+ parts of the aggregate.
232
+
233
+ 6. Conveying Non-Source Forms.
234
+
235
+ You may convey a covered work in object code form under the terms
236
+ of sections 4 and 5, provided that you also convey the
237
+ machine-readable Corresponding Source under the terms of this License,
238
+ in one of these ways:
239
+
240
+ a) Convey the object code in, or embodied in, a physical product
241
+ (including a physical distribution medium), accompanied by the
242
+ Corresponding Source fixed on a durable physical medium
243
+ customarily used for software interchange.
244
+
245
+ b) Convey the object code in, or embodied in, a physical product
246
+ (including a physical distribution medium), accompanied by a
247
+ written offer, valid for at least three years and valid for as
248
+ long as you offer spare parts or customer support for that product
249
+ model, to give anyone who possesses the object code either (1) a
250
+ copy of the Corresponding Source for all the software in the
251
+ product that is covered by this License, on a durable physical
252
+ medium customarily used for software interchange, for a price no
253
+ more than your reasonable cost of physically performing this
254
+ conveying of source, or (2) access to copy the
255
+ Corresponding Source from a network server at no charge.
256
+
257
+ c) Convey individual copies of the object code with a copy of the
258
+ written offer to provide the Corresponding Source. This
259
+ alternative is allowed only occasionally and noncommercially, and
260
+ only if you received the object code with such an offer, in accord
261
+ with subsection 6b.
262
+
263
+ d) Convey the object code by offering access from a designated
264
+ place (gratis or for a charge), and offer equivalent access to the
265
+ Corresponding Source in the same way through the same place at no
266
+ further charge. You need not require recipients to copy the
267
+ Corresponding Source along with the object code. If the place to
268
+ copy the object code is a network server, the Corresponding Source
269
+ may be on a different server (operated by you or a third party)
270
+ that supports equivalent copying facilities, provided you maintain
271
+ clear directions next to the object code saying where to find the
272
+ Corresponding Source. Regardless of what server hosts the
273
+ Corresponding Source, you remain obligated to ensure that it is
274
+ available for as long as needed to satisfy these requirements.
275
+
276
+ e) Convey the object code using peer-to-peer transmission, provided
277
+ you inform other peers where the object code and Corresponding
278
+ Source of the work are being offered to the general public at no
279
+ charge under subsection 6d.
280
+
281
+ A separable portion of the object code, whose source code is excluded
282
+ from the Corresponding Source as a System Library, need not be
283
+ included in conveying the object code work.
284
+
285
+ A "User Product" is either (1) a "consumer product", which means any
286
+ tangible personal property which is normally used for personal, family,
287
+ or household purposes, or (2) anything designed or sold for incorporation
288
+ into a dwelling. In determining whether a product is a consumer product,
289
+ doubtful cases shall be resolved in favor of coverage. For a particular
290
+ product received by a particular user, "normally used" refers to a
291
+ typical or common use of that class of product, regardless of the status
292
+ of the particular user or of the way in which the particular user
293
+ actually uses, or expects or is expected to use, the product. A product
294
+ is a consumer product regardless of whether the product has substantial
295
+ commercial, industrial or non-consumer uses, unless such uses represent
296
+ the only significant mode of use of the product.
297
+
298
+ "Installation Information" for a User Product means any methods,
299
+ procedures, authorization keys, or other information required to install
300
+ and execute modified versions of a covered work in that User Product from
301
+ a modified version of its Corresponding Source. The information must
302
+ suffice to ensure that the continued functioning of the modified object
303
+ code is in no case prevented or interfered with solely because
304
+ modification has been made.
305
+
306
+ If you convey an object code work under this section in, or with, or
307
+ specifically for use in, a User Product, and the conveying occurs as
308
+ part of a transaction in which the right of possession and use of the
309
+ User Product is transferred to the recipient in perpetuity or for a
310
+ fixed term (regardless of how the transaction is characterized), the
311
+ Corresponding Source conveyed under this section must be accompanied
312
+ by the Installation Information. But this requirement does not apply
313
+ if neither you nor any third party retains the ability to install
314
+ modified object code on the User Product (for example, the work has
315
+ been installed in ROM).
316
+
317
+ The requirement to provide Installation Information does not include a
318
+ requirement to continue to provide support service, warranty, or updates
319
+ for a work that has been modified or installed by the recipient, or for
320
+ the User Product in which it has been modified or installed. Access to a
321
+ network may be denied when the modification itself materially and
322
+ adversely affects the operation of the network or violates the rules and
323
+ protocols for communication across the network.
324
+
325
+ Corresponding Source conveyed, and Installation Information provided,
326
+ in accord with this section must be in a format that is publicly
327
+ documented (and with an implementation available to the public in
328
+ source code form), and must require no special password or key for
329
+ unpacking, reading or copying.
330
+
331
+ 7. Additional Terms.
332
+
333
+ "Additional permissions" are terms that supplement the terms of this
334
+ License by making exceptions from one or more of its conditions.
335
+ Additional permissions that are applicable to the entire Program shall
336
+ be treated as though they were included in this License, to the extent
337
+ that they are valid under applicable law. If additional permissions
338
+ apply only to part of the Program, that part may be used separately
339
+ under those permissions, but the entire Program remains governed by
340
+ this License without regard to the additional permissions.
341
+
342
+ When you convey a copy of a covered work, you may at your option
343
+ remove any additional permissions from that copy, or from any part of
344
+ it. (Additional permissions may be written to require their own
345
+ removal in certain cases when you modify the work.) You may place
346
+ additional permissions on material, added by you to a covered work,
347
+ for which you have or can give appropriate copyright permission.
348
+
349
+ Notwithstanding any other provision of this License, for material you
350
+ add to a covered work, you may (if authorized by the copyright holders of
351
+ that material) supplement the terms of this License with terms:
352
+
353
+ a) Disclaiming warranty or limiting liability differently from the
354
+ terms of sections 15 and 16 of this License; or
355
+
356
+ b) Requiring preservation of specified reasonable legal notices or
357
+ author attributions in that material or in the Appropriate Legal
358
+ Notices displayed by works containing it; or
359
+
360
+ c) Prohibiting misrepresentation of the origin of that material, or
361
+ requiring that modified versions of such material be marked in
362
+ reasonable ways as different from the original version; or
363
+
364
+ d) Limiting the use for publicity purposes of names of licensors or
365
+ authors of the material; or
366
+
367
+ e) Declining to grant rights under trademark law for use of some
368
+ trade names, trademarks, or service marks; or
369
+
370
+ f) Requiring indemnification of licensors and authors of that
371
+ material by anyone who conveys the material (or modified versions of
372
+ it) with contractual assumptions of liability to the recipient, for
373
+ any liability that these contractual assumptions directly impose on
374
+ those licensors and authors.
375
+
376
+ All other non-permissive additional terms are considered "further
377
+ restrictions" within the meaning of section 10. If the Program as you
378
+ received it, or any part of it, contains a notice stating that it is
379
+ governed by this License along with a term that is a further
380
+ restriction, you may remove that term. If a license document contains
381
+ a further restriction but permits relicensing or conveying under this
382
+ License, you may add to a covered work material governed by the terms
383
+ of that license document, provided that the further restriction does
384
+ not survive such relicensing or conveying.
385
+
386
+ If you add terms to a covered work in accord with this section, you
387
+ must place, in the relevant source files, a statement of the
388
+ additional terms that apply to those files, or a notice indicating
389
+ where to find the applicable terms.
390
+
391
+ Additional terms, permissive or non-permissive, may be stated in the
392
+ form of a separately written license, or stated as exceptions;
393
+ the above requirements apply either way.
394
+
395
+ 8. Termination.
396
+
397
+ You may not propagate or modify a covered work except as expressly
398
+ provided under this License. Any attempt otherwise to propagate or
399
+ modify it is void, and will automatically terminate your rights under
400
+ this License (including any patent licenses granted under the third
401
+ paragraph of section 11).
402
+
403
+ However, if you cease all violation of this License, then your
404
+ license from a particular copyright holder is reinstated (a)
405
+ provisionally, unless and until the copyright holder explicitly and
406
+ finally terminates your license, and (b) permanently, if the copyright
407
+ holder fails to notify you of the violation by some reasonable means
408
+ prior to 60 days after the cessation.
409
+
410
+ Moreover, your license from a particular copyright holder is
411
+ reinstated permanently if the copyright holder notifies you of the
412
+ violation by some reasonable means, this is the first time you have
413
+ received notice of violation of this License (for any work) from that
414
+ copyright holder, and you cure the violation prior to 30 days after
415
+ your receipt of the notice.
416
+
417
+ Termination of your rights under this section does not terminate the
418
+ licenses of parties who have received copies or rights from you under
419
+ this License. If your rights have been terminated and not permanently
420
+ reinstated, you do not qualify to receive new licenses for the same
421
+ material under section 10.
422
+
423
+ 9. Acceptance Not Required for Having Copies.
424
+
425
+ You are not required to accept this License in order to receive or
426
+ run a copy of the Program. Ancillary propagation of a covered work
427
+ occurring solely as a consequence of using peer-to-peer transmission
428
+ to receive a copy likewise does not require acceptance. However,
429
+ nothing other than this License grants you permission to propagate or
430
+ modify any covered work. These actions infringe copyright if you do
431
+ not accept this License. Therefore, by modifying or propagating a
432
+ covered work, you indicate your acceptance of this License to do so.
433
+
434
+ 10. Automatic Licensing of Downstream Recipients.
435
+
436
+ Each time you convey a covered work, the recipient automatically
437
+ receives a license from the original licensors, to run, modify and
438
+ propagate that work, subject to this License. You are not responsible
439
+ for enforcing compliance by third parties with this License.
440
+
441
+ An "entity transaction" is a transaction transferring control of an
442
+ organization, or substantially all assets of one, or subdividing an
443
+ organization, or merging organizations. If propagation of a covered
444
+ work results from an entity transaction, each party to that
445
+ transaction who receives a copy of the work also receives whatever
446
+ licenses to the work the party's predecessor in interest had or could
447
+ give under the previous paragraph, plus a right to possession of the
448
+ Corresponding Source of the work from the predecessor in interest, if
449
+ the predecessor has it or can get it with reasonable efforts.
450
+
451
+ You may not impose any further restrictions on the exercise of the
452
+ rights granted or affirmed under this License. For example, you may
453
+ not impose a license fee, royalty, or other charge for exercise of
454
+ rights granted under this License, and you may not initiate litigation
455
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
456
+ any patent claim is infringed by making, using, selling, offering for
457
+ sale, or importing the Program or any portion of it.
458
+
459
+ 11. Patents.
460
+
461
+ A "contributor" is a copyright holder who authorizes use under this
462
+ License of the Program or a work on which the Program is based. The
463
+ work thus licensed is called the contributor's "contributor version".
464
+
465
+ A contributor's "essential patent claims" are all patent claims
466
+ owned or controlled by the contributor, whether already acquired or
467
+ hereafter acquired, that would be infringed by some manner, permitted
468
+ by this License, of making, using, or selling its contributor version,
469
+ but do not include claims that would be infringed only as a
470
+ consequence of further modification of the contributor version. For
471
+ purposes of this definition, "control" includes the right to grant
472
+ patent sublicenses in a manner consistent with the requirements of
473
+ this License.
474
+
475
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
476
+ patent license under the contributor's essential patent claims, to
477
+ make, use, sell, offer for sale, import and otherwise run, modify and
478
+ propagate the contents of its contributor version.
479
+
480
+ In the following three paragraphs, a "patent license" is any express
481
+ agreement or commitment, however denominated, not to enforce a patent
482
+ (such as an express permission to practice a patent or covenant not to
483
+ sue for patent infringement). To "grant" such a patent license to a
484
+ party means to make such an agreement or commitment not to enforce a
485
+ patent against the party.
486
+
487
+ If you convey a covered work, knowingly relying on a patent license,
488
+ and the Corresponding Source of the work is not available for anyone
489
+ to copy, free of charge and under the terms of this License, through a
490
+ publicly available network server or other readily accessible means,
491
+ then you must either (1) cause the Corresponding Source to be so
492
+ available, or (2) arrange to deprive yourself of the benefit of the
493
+ patent license for this particular work, or (3) arrange, in a manner
494
+ consistent with the requirements of this License, to extend the patent
495
+ license to downstream recipients. "Knowingly relying" means you have
496
+ actual knowledge that, but for the patent license, your conveying the
497
+ covered work in a country, or your recipient's use of the covered work
498
+ in a country, would infringe one or more identifiable patents in that
499
+ country that you have reason to believe are valid.
500
+
501
+ If, pursuant to or in connection with a single transaction or
502
+ arrangement, you convey, or propagate by procuring conveyance of, a
503
+ covered work, and grant a patent license to some of the parties
504
+ receiving the covered work authorizing them to use, propagate, modify
505
+ or convey a specific copy of the covered work, then the patent license
506
+ you grant is automatically extended to all recipients of the covered
507
+ work and works based on it.
508
+
509
+ A patent license is "discriminatory" if it does not include within
510
+ the scope of its coverage, prohibits the exercise of, or is
511
+ conditioned on the non-exercise of one or more of the rights that are
512
+ specifically granted under this License. You may not convey a covered
513
+ work if you are a party to an arrangement with a third party that is
514
+ in the business of distributing software, under which you make payment
515
+ to the third party based on the extent of your activity of conveying
516
+ the work, and under which the third party grants, to any of the
517
+ parties who would receive the covered work from you, a discriminatory
518
+ patent license (a) in connection with copies of the covered work
519
+ conveyed by you (or copies made from those copies), or (b) primarily
520
+ for and in connection with specific products or compilations that
521
+ contain the covered work, unless you entered into that arrangement,
522
+ or that patent license was granted, prior to 28 March 2007.
523
+
524
+ Nothing in this License shall be construed as excluding or limiting
525
+ any implied license or other defenses to infringement that may
526
+ otherwise be available to you under applicable patent law.
527
+
528
+ 12. No Surrender of Others' Freedom.
529
+
530
+ If conditions are imposed on you (whether by court order, agreement or
531
+ otherwise) that contradict the conditions of this License, they do not
532
+ excuse you from the conditions of this License. If you cannot convey a
533
+ covered work so as to satisfy simultaneously your obligations under this
534
+ License and any other pertinent obligations, then as a consequence you may
535
+ not convey it at all. For example, if you agree to terms that obligate you
536
+ to collect a royalty for further conveying from those to whom you convey
537
+ the Program, the only way you could satisfy both those terms and this
538
+ License would be to refrain entirely from conveying the Program.
539
+
540
+ 13. Remote Network Interaction; Use with the GNU General Public License.
541
+
542
+ Notwithstanding any other provision of this License, if you modify the
543
+ Program, your modified version must prominently offer all users
544
+ interacting with it remotely through a computer network (if your version
545
+ supports such interaction) an opportunity to receive the Corresponding
546
+ Source of your version by providing access to the Corresponding Source
547
+ from a network server at no charge, through some standard or customary
548
+ means of facilitating copying of software. This Corresponding Source
549
+ shall include the Corresponding Source for any work covered by version 3
550
+ of the GNU General Public License that is incorporated pursuant to the
551
+ following paragraph.
552
+
553
+ Notwithstanding any other provision of this License, you have
554
+ permission to link or combine any covered work with a work licensed
555
+ under version 3 of the GNU General Public License into a single
556
+ combined work, and to convey the resulting work. The terms of this
557
+ License will continue to apply to the part which is the covered work,
558
+ but the work with which it is combined will remain governed by version
559
+ 3 of the GNU General Public License.
560
+
561
+ 14. Revised Versions of this License.
562
+
563
+ The Free Software Foundation may publish revised and/or new versions of
564
+ the GNU Affero General Public License from time to time. Such new versions
565
+ will be similar in spirit to the present version, but may differ in detail to
566
+ address new problems or concerns.
567
+
568
+ Each version is given a distinguishing version number. If the
569
+ Program specifies that a certain numbered version of the GNU Affero General
570
+ Public License "or any later version" applies to it, you have the
571
+ option of following the terms and conditions either of that numbered
572
+ version or of any later version published by the Free Software
573
+ Foundation. If the Program does not specify a version number of the
574
+ GNU Affero General Public License, you may choose any version ever published
575
+ by the Free Software Foundation.
576
+
577
+ If the Program specifies that a proxy can decide which future
578
+ versions of the GNU Affero General Public License can be used, that proxy's
579
+ public statement of acceptance of a version permanently authorizes you
580
+ to choose that version for the Program.
581
+
582
+ Later license versions may give you additional or different
583
+ permissions. However, no additional obligations are imposed on any
584
+ author or copyright holder as a result of your choosing to follow a
585
+ later version.
586
+
587
+ 15. Disclaimer of Warranty.
588
+
589
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597
+
598
+ 16. Limitation of Liability.
599
+
600
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608
+ SUCH DAMAGES.
609
+
610
+ 17. Interpretation of Sections 15 and 16.
611
+
612
+ If the disclaimer of warranty and limitation of liability provided
613
+ above cannot be given local legal effect according to their terms,
614
+ reviewing courts shall apply local law that most closely approximates
615
+ an absolute waiver of all civil liability in connection with the
616
+ Program, unless a warranty or assumption of liability accompanies a
617
+ copy of the Program in return for a fee.
618
+
619
+ END OF TERMS AND CONDITIONS
620
+
621
+ How to Apply These Terms to Your New Programs
622
+
623
+ If you develop a new program, and you want it to be of the greatest
624
+ possible use to the public, the best way to achieve this is to make it
625
+ free software which everyone can redistribute and change under these terms.
626
+
627
+ To do so, attach the following notices to the program. It is safest
628
+ to attach them to the start of each source file to most effectively
629
+ state the exclusion of warranty; and each file should have at least
630
+ the "copyright" line and a pointer to where the full notice is found.
631
+
632
+ <one line to give the program's name and a brief idea of what it does.>
633
+ Copyright (C) <year> <name of author>
634
+
635
+ This program is free software: you can redistribute it and/or modify
636
+ it under the terms of the GNU Affero General Public License as published by
637
+ the Free Software Foundation, either version 3 of the License, or
638
+ (at your option) any later version.
639
+
640
+ This program is distributed in the hope that it will be useful,
641
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
642
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643
+ GNU Affero General Public License for more details.
644
+
645
+ You should have received a copy of the GNU Affero General Public License
646
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
647
+
648
+ Also add information on how to contact you by electronic and paper mail.
649
+
650
+ If your software can interact with users remotely through a computer
651
+ network, you should also make sure that it provides a way for users to
652
+ get its source. For example, if your program is a web application, its
653
+ interface could display a "Source" link that leads users to an archive
654
+ of the code. There are many ways you could offer source, and different
655
+ solutions will be better for different programs; see section 13 for the
656
+ specific requirements.
657
+
658
+ You should also get your employer (if you work as a programmer) or school,
659
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
660
+ For more information on this, and how to apply and follow the GNU AGPL, see
661
+ <http://www.gnu.org/licenses/>.
src/hwp5/README ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ pyhwp
2
+ =====
3
+
4
+ HWP Document Format v5 parser & processor.
5
+
6
+ Features
7
+ --------
8
+
9
+ - Analyze and extract internal streams out from a HWP Document Format v5 file
10
+ - (*Experimental*) Conversion to OpenDocument format (.odt) or plain text (.txt)
11
+
12
+ Installation
13
+ ------------
14
+
15
+ from `pypi <http://pypi.org/project/pyhwp>`_::
16
+
17
+ virtualenv pyhwp
18
+ pyhwp/bin/pip install --pre pyhwp # Install pyhwp into a virtualenv directory
19
+
20
+ Or::
21
+
22
+ pip install --user --pre pyhwp # Install pyhwp into user's home directory
23
+
24
+ Requirements
25
+ ------------
26
+
27
+ - Python 2.7, 3.5, 3.6, 3.7 or 3.8
28
+ - `cryptography <https://pypi.org/project/cryptography>`_
29
+ - `lxml <https://pypi.org/project/lxml>`_
30
+ - `olefile <https://pypi.org/project/olefile>`_
31
+
32
+ Documentation & Development
33
+ ---------------------------
34
+
35
+ - Documentation: `https://pyhwp.readthedocs.io <https://pyhwp.readthedocs.io>`_ [`한국/조선어 <https://pyhwp.readthedocs.io/ko/latest>`_]
36
+ - Distribution: `https://pypi.org/project/pyhwp/ <https://pypi.org/project/pyhwp/>`_
37
+ - Development: `https://github.com/mete0r/pyhwp <https://github.com/mete0r/pyhwp>`_
38
+ - Issue tracker: `https://github.com/mete0r/pyhwp/issues <https://github.com/mete0r/pyhwp/issues>`_
39
+ - Feedbacks & contributions are welcome!
40
+
41
+ Contributors
42
+ ------------
43
+
44
+ Maintainer: `mete0r <https://github.com/mete0r>`_
45
+
46
+ License
47
+ -------
48
+
49
+ Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
50
+
51
+ .. image:: http://www.gnu.org/graphics/agplv3-155x51.png
52
+
53
+ `GNU Affero General Public License v3.0 <http://www.gnu.org/licenses/agpl-3.0.html>`_
54
+ `(text version) <http://www.gnu.org/licenses/agpl-3.0.txt>`_
55
+
56
+ This program is free software: you can redistribute it and/or modify
57
+ it under the terms of the GNU Affero General Public License as published by
58
+ the Free Software Foundation, either version 3 of the License, or
59
+ (at your option) any later version.
60
+
61
+ This program is distributed in the hope that it will be useful,
62
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
63
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
64
+ GNU Affero General Public License for more details.
65
+
66
+ You should have received a copy of the GNU Affero General Public License
67
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
68
+
69
+ Disclosure
70
+ ----------
71
+
72
+ This program has been developed in accordance with a public document named "HWP
73
+ Binary Specification 1.1" published by `Hancom Inc. <http://www.hancom.co.kr>`_
src/hwp5/VERSION.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ 1.0.2
src/hwp5/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ from __future__ import with_statement
19
+ import os.path
20
+
21
+ try:
22
+ with open(os.path.join(os.path.dirname(__file__), 'VERSION.txt')) as f:
23
+ __version__ = f.read().strip()
24
+ del f
25
+ except Exception:
26
+ __version__ = '0.0-unknown'
src/hwp5/binmodel/__init__.py ADDED
@@ -0,0 +1,549 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+ from io import BytesIO
23
+ from itertools import takewhile
24
+ import json
25
+ import logging
26
+ import inspect
27
+
28
+ from .. import recordstream
29
+ from ..bintype import ERROREVENT
30
+ from ..bintype import resolve_type_events
31
+ from ..bintype import resolve_values_from_stream
32
+ from ..dataio import ParseError
33
+ from ..dataio import dumpbytes
34
+ from ..recordstream import nth
35
+ from ..tagids import tagnames
36
+ from ..treeop import STARTEVENT
37
+ from ..treeop import ENDEVENT
38
+ from ..treeop import prefix_ancestors_from_level
39
+ from ..utils import JsonObjects
40
+
41
+ from ._shared import tag_models
42
+ from ._shared import RecordModel
43
+ from ._shared import BinStorageId
44
+ from ._shared import COLORREF
45
+ from ._shared import Margin
46
+ from .controlchar import CHID
47
+ from .controlchar import ControlChar
48
+ from .tagid16_document_properties import DocumentProperties
49
+ from .tagid17_id_mappings import IdMappings
50
+ from .tagid18_bin_data import BinData
51
+ from .tagid20_border_fill import BorderFill
52
+ from .tagid19_face_name import FaceName
53
+ from .tagid21_char_shape import CharShape
54
+ from .tagid21_char_shape import LanguageStruct
55
+ from .tagid22_tab_def import TabDef
56
+ from .tagid23_numbering import Numbering
57
+ from .tagid24_bullet import Bullet
58
+ from .tagid25_para_shape import ParaShape
59
+ from .tagid26_style import Style
60
+ from .tagid27_doc_data import DocData
61
+ from .tagid28_distribute_doc_data import DistributeDocData
62
+ from .tagid30_compatible_document import CompatibleDocument
63
+ from .tagid31_layout_compatibility import LayoutCompatibility
64
+ from .tagid32_unknown import TagModel32
65
+ from .tagid50_para_header import Paragraph
66
+ from .tagid51_para_text import ParaText
67
+ from .tagid51_para_text import ParaTextChunks
68
+ from .tagid52_para_char_shape import ParaCharShape
69
+ from .tagid53_para_line_seg import ParaLineSeg
70
+ from .tagid53_para_line_seg import ParaLineSegList
71
+ from .tagid53_para_line_seg import LineSeg
72
+ from .tagid54_para_range_tag import ParaRangeTag
73
+ from .tagid55_ctrl_header import Control
74
+ from .controls.bookmark_control import BookmarkControl
75
+ from .controls.columns_def import ColumnsDef
76
+ from .controls.common_controls import CommonControl
77
+ from .controls.dutmal import Dutmal
78
+ from .controls.field import Field
79
+ from .controls.field import FieldUnknown
80
+ from .controls.field import FieldDate
81
+ from .controls.field import FieldDocDate
82
+ from .controls.field import FieldPath
83
+ from .controls.field import FieldBookmark
84
+ from .controls.field import FieldMailMerge
85
+ from .controls.field import FieldCrossRef
86
+ from .controls.field import FieldFormula
87
+ from .controls.field import FieldClickHere
88
+ from .controls.field import FieldClickHereData
89
+ from .controls.field import FieldSummary
90
+ from .controls.field import FieldUserInfo
91
+ from .controls.field import FieldHyperLink
92
+ from .controls.field import FieldMemo
93
+ from .controls.field import FieldPrivateInfoSecurity
94
+ from .controls.gshape_object_control import GShapeObjectControl
95
+ from .controls.header_footer import HeaderFooter
96
+ from .controls.header_footer import Header
97
+ from .controls.header_footer import Footer
98
+ from .controls.hidden_comment import HiddenComment
99
+ from .controls.index_marker import IndexMarker
100
+ from .controls.note import Note
101
+ from .controls.note import FootNote
102
+ from .controls.note import EndNote
103
+ from .controls.numbering import AutoNumbering
104
+ from .controls.numbering import NewNumbering
105
+ from .controls.page_hide import PageHide
106
+ from .controls.page_number_position import PageNumberPosition
107
+ from .controls.page_odd_even import PageOddEven
108
+ from .controls.section_def import SectionDef
109
+ from .controls.table_control import TableControl
110
+ from .controls.tcps_control import TCPSControl
111
+ from .tagid56_list_header import ListHeader
112
+ from .tagid56_list_header import TableCaption
113
+ from .tagid56_list_header import TableCell
114
+ from .tagid56_list_header import TextboxParagraphList
115
+ from .tagid56_list_header import HeaderParagraphList
116
+ from .tagid56_list_header import FooterParagraphList
117
+ from .tagid57_page_def import PageDef
118
+ from .tagid58_footnote_shape import FootnoteShape
119
+ from .tagid59_page_border_fill import PageBorderFill
120
+ from .tagid60_shape_component import ShapeComponent
121
+ from .tagid61_table import TableBody
122
+ from .tagid62_shape_component_line import ShapeLine
123
+ from .tagid63_shape_component_rectangle import ShapeRectangle
124
+ from .tagid64_shape_component_ellipse import ShapeEllipse
125
+ from .tagid65_shape_component_arc import ShapeArc
126
+ from .tagid66_shape_component_polygon import ShapePolygon
127
+ from .tagid67_shape_component_curve import ShapeCurve
128
+ from .tagid68_shape_component_ole import ShapeOLE
129
+ from .tagid69_shape_component_picture import ShapePicture
130
+ from .tagid70_shape_component_container import ShapeContainer
131
+ from .tagid71_ctrl_data import ControlData
132
+ from .tagid72_ctrl_eqedit import EqEdit
133
+ from .tagid74_shape_component_textart import ShapeTextArt
134
+ from .tagid75_form_object import FormObject
135
+ from .tagid76_memo_shape import MemoShape
136
+ from .tagid77_memo_list import MemoList
137
+ from .tagid78_forbidden_char import ForbiddenChar
138
+ from .tagid79_chart_data import ChartData
139
+ from .tagid99_shape_component_unknown import ShapeUnknown
140
+
141
+ # to suppress pyflake8 warning 'imported but not used'
142
+ RecordModel
143
+ BinStorageId
144
+ COLORREF
145
+ Margin
146
+ DocumentProperties
147
+ BinData
148
+ BorderFill
149
+ CharShape
150
+ LanguageStruct
151
+ TabDef
152
+ Numbering
153
+ Bullet
154
+ ParaShape
155
+ Style
156
+ DocData
157
+ DistributeDocData
158
+ CompatibleDocument
159
+ LayoutCompatibility
160
+ TagModel32
161
+ Paragraph
162
+ ParaText
163
+ ParaTextChunks
164
+ ParaCharShape
165
+ ParaLineSeg
166
+ ParaLineSegList
167
+ LineSeg
168
+ ParaRangeTag
169
+ Control
170
+ ListHeader
171
+ TableCaption
172
+ TableCell
173
+ TextboxParagraphList
174
+ PageDef
175
+ FootnoteShape
176
+ PageBorderFill
177
+ ShapeComponent
178
+ TableBody
179
+ ShapeLine
180
+ ShapeRectangle
181
+ ShapeEllipse
182
+ ShapeArc
183
+ ShapePolygon
184
+ ShapeCurve
185
+ ShapeOLE
186
+ ShapePicture
187
+ ShapeContainer
188
+ ControlData
189
+ EqEdit
190
+ ShapeTextArt
191
+ FormObject
192
+ MemoShape
193
+ MemoList
194
+ ForbiddenChar
195
+ ChartData
196
+ ShapeUnknown
197
+ CHID
198
+ ControlChar
199
+ BookmarkControl
200
+ ColumnsDef
201
+ CommonControl
202
+ Dutmal
203
+ Field
204
+ FieldUnknown
205
+ FieldDate
206
+ FieldDocDate
207
+ FieldPath
208
+ FieldBookmark
209
+ FieldMailMerge
210
+ FieldCrossRef
211
+ FieldFormula
212
+ FieldClickHere
213
+ FieldClickHereData
214
+ FieldSummary
215
+ FieldUserInfo
216
+ FieldHyperLink
217
+ FieldMemo
218
+ FieldPrivateInfoSecurity
219
+ GShapeObjectControl
220
+ HeaderFooter
221
+ Header
222
+ HeaderParagraphList
223
+ Footer
224
+ FooterParagraphList
225
+ HiddenComment
226
+ IndexMarker
227
+ Note
228
+ FootNote
229
+ EndNote
230
+ AutoNumbering
231
+ NewNumbering
232
+ PageHide
233
+ PageNumberPosition
234
+ PageOddEven
235
+ SectionDef
236
+ TableControl
237
+ TCPSControl
238
+
239
+
240
+ logger = logging.getLogger(__name__)
241
+
242
+
243
+ class UnknownTagModel(RecordModel):
244
+ pass
245
+
246
+
247
+ class Text(object):
248
+ pass
249
+
250
+
251
+ def _check_tag_models():
252
+ for tagid, name in tagnames.items():
253
+ assert tagid in tag_models, 'RecordModel for %s is missing!' % name
254
+
255
+
256
+ _check_tag_models()
257
+
258
+
259
+ def init_record_parsing_context(base, record):
260
+ ''' Initialize a context to parse the given record
261
+
262
+ the initializations includes followings:
263
+ - context = dict(base)
264
+ - context['record'] = record
265
+ - context['stream'] = record payload stream
266
+
267
+ :param base: the base context to be shallow-copied into the new one
268
+ :param record: to be parsed
269
+ :returns: new context
270
+ '''
271
+
272
+ return dict(base, record=record, stream=BytesIO(record['payload']))
273
+
274
+
275
+ def parse_models(context, records):
276
+ for context, model in parse_models_intern(context, records):
277
+ yield model
278
+
279
+
280
+ def parse_models_intern(context, records):
281
+ context_models = ((init_record_parsing_context(context, record), record)
282
+ for record in records)
283
+ context_models = parse_models_with_parent(context_models)
284
+ for context, model in context_models:
285
+ stream = context['stream']
286
+ unparsed = stream.read()
287
+ if unparsed:
288
+ model['unparsed'] = unparsed
289
+ yield context, model
290
+
291
+
292
+ def parse_models_with_parent(context_models):
293
+ level_prefixed = ((model['level'], (context, model))
294
+ for context, model in context_models)
295
+ root_item = (dict(), dict())
296
+ ancestors_prefixed = prefix_ancestors_from_level(level_prefixed, root_item)
297
+ for ancestors, (context, model) in ancestors_prefixed:
298
+ context['parent'] = ancestors[-1]
299
+ parse_model(context, model)
300
+ yield context, model
301
+
302
+
303
+ def parse_model(context, model):
304
+ ''' HWPTAG로 모델 결정 후 기본 파싱 '''
305
+
306
+ stream = context['stream']
307
+ context['resolve_values'] = resolve_values_from_stream(stream)
308
+ events = resolve_model_events(context, model)
309
+ events = raise_on_errorevent(context, events)
310
+ model['binevents'] = list(events)
311
+
312
+ logger.debug('model: %s', model['type'].__name__)
313
+ logger.debug('%s', model['content'])
314
+
315
+
316
+ def raise_on_errorevent(context, events):
317
+ binevents = list()
318
+ for ev, item in events:
319
+ yield ev, item
320
+ binevents.append((ev, item))
321
+ if ev is ERROREVENT:
322
+ e = item['exception']
323
+ msg = 'can\'t parse %s' % item['type']
324
+ pe = ParseError(msg)
325
+ pe.cause = e
326
+ pe.path = context.get('path')
327
+ pe.treegroup = context.get('treegroup')
328
+ pe.record = context.get('record')
329
+ pe.offset = item.get('bin_offset')
330
+ pe.binevents = binevents
331
+ raise pe
332
+
333
+
334
+ def resolve_models(context, records):
335
+ model_contexts = (dict(context, record=record, model=dict(record))
336
+ for record in records)
337
+
338
+ level_prefixed = ((context['model']['level'], context)
339
+ for context in model_contexts)
340
+ root_item = {}
341
+ ancestors_prefixed = prefix_ancestors_from_level(level_prefixed, root_item)
342
+ for ancestors, context in ancestors_prefixed:
343
+ parent = ancestors[-1]
344
+ context['parent'] = parent, parent.get('model', {})
345
+
346
+ record_frame = context['record']
347
+ context['type'] = RecordModel
348
+ context['name'] = record_frame['tagname']
349
+ yield STARTEVENT, context
350
+ for x in resolve_model_events(context, context['model']):
351
+ yield x
352
+ event, item = x
353
+ context['value'] = item
354
+ yield ENDEVENT, context
355
+
356
+
357
+ def resolve_model_events(context, model):
358
+
359
+ resolve_values = context['resolve_values']
360
+
361
+ model['type'] = model_type = tag_models.get(model['tagid'],
362
+ UnknownTagModel)
363
+
364
+ for ev, item in resolve_type_events(model_type, context, resolve_values):
365
+ yield ev, item
366
+
367
+ model['content'] = item['value']
368
+
369
+ extension_types = getattr(model['type'], 'extension_types', None)
370
+ if extension_types:
371
+ key = model['type'].get_extension_key(context, model)
372
+ extension = extension_types.get(key)
373
+ if extension is not None:
374
+ # 예: Control -> TableControl로 바뀌는 경우,
375
+ # Control의 member들은 이미 읽은 상태이고
376
+ # CommonControl, TableControl에서 각각 정의한
377
+ # 멤버들을 읽어들여야 함
378
+ for cls in get_extension_mro(extension, model['type']):
379
+ extension_type_events = resolve_type_events(cls, context,
380
+ resolve_values)
381
+ for ev, item in extension_type_events:
382
+ yield ev, item
383
+ content = item['value']
384
+ model['content'].update(content)
385
+ model['type'] = extension
386
+
387
+ if 'parent' in context:
388
+ parent = context['parent']
389
+ parent_context, parent_model = parent
390
+ parent_type = parent_model.get('type')
391
+ parent_content = parent_model.get('content')
392
+
393
+ on_child = getattr(parent_type, 'on_child', None)
394
+ if on_child:
395
+ on_child(parent_content, parent_context, (context, model))
396
+
397
+
398
+ def get_extension_mro(cls, up_to_cls=None):
399
+ mro = inspect.getmro(cls)
400
+ mro = takewhile(lambda cls: cls is not up_to_cls, mro)
401
+ mro = list(cls for cls in mro if 'attributes' in cls.__dict__)
402
+ mro = reversed(mro)
403
+ return mro
404
+
405
+
406
+ class ModelJsonEncoder(json.JSONEncoder):
407
+
408
+ def default(self, obj):
409
+ if isinstance(obj, bytes):
410
+ return obj.decode('latin1')
411
+ return json.JSONEncoder.default(self, obj)
412
+
413
+
414
+ def model_to_json(model, *args, **kwargs):
415
+ ''' convert a model to json '''
416
+ kwargs['cls'] = ModelJsonEncoder
417
+ model = dict(model)
418
+ model['type'] = model['type'].__name__
419
+ record = model
420
+ record['payload'] = list(dumpbytes(record['payload']))
421
+ if 'unparsed' in model:
422
+ model['unparsed'] = list(dumpbytes(model['unparsed']))
423
+ if 'binevents' in model:
424
+ del model['binevents']
425
+ return json.dumps(model, *args, **kwargs)
426
+
427
+
428
+ def chain_iterables(iterables):
429
+ for iterable in iterables:
430
+ for item in iterable:
431
+ yield item
432
+
433
+
434
+ class ModelStream(recordstream.RecordStream):
435
+
436
+ def models(self, **kwargs):
437
+ # prepare binmodel parsing context
438
+ kwargs.setdefault('version', self.version)
439
+ try:
440
+ kwargs.setdefault('path', self.path)
441
+ except AttributeError:
442
+ pass
443
+ treegroup = kwargs.get('treegroup', None)
444
+ if treegroup is not None:
445
+ records = self.records_treegroup(treegroup) # TODO: kwargs
446
+ models = parse_models(kwargs, records)
447
+ else:
448
+ groups = self.models_treegrouped(**kwargs)
449
+ models = chain_iterables(groups)
450
+ return models
451
+
452
+ def models_treegrouped(self, **kwargs):
453
+ ''' iterable of iterable of the models, grouped by the top-level tree
454
+ '''
455
+ kwargs.setdefault('version', self.version)
456
+ for group_idx, records in enumerate(self.records_treegrouped()):
457
+ kwargs['treegroup'] = group_idx
458
+ yield parse_models(kwargs, records)
459
+
460
+ def model(self, idx):
461
+ return nth(self.models(), idx)
462
+
463
+ def models_json(self, **kwargs):
464
+ models = self.models(**kwargs)
465
+ return JsonObjects(models, model_to_json)
466
+
467
+ def other_formats(self):
468
+ d = super(ModelStream, self).other_formats()
469
+ d['.models'] = self.models_json().open
470
+ return d
471
+
472
+ def parse_model_events(self):
473
+ context = dict(version=self.version)
474
+
475
+ def resolve_values_from_record(record):
476
+ stream = BytesIO(record['payload'])
477
+ return resolve_values_from_stream(stream)
478
+
479
+ for group_idx, records in enumerate(self.records_treegrouped()):
480
+ context['treegroup'] = group_idx
481
+ for x in resolve_models(context, records):
482
+ event, item = x
483
+ if item['type'] is RecordModel:
484
+ if event is STARTEVENT:
485
+ record_frame = item['record']
486
+ stream = BytesIO(record_frame['payload'])
487
+ resolve_values = resolve_values_from_stream(stream)
488
+ item['stream'] = stream
489
+ item['resolve_values'] = resolve_values
490
+ elif event is ENDEVENT:
491
+ stream = item['stream']
492
+ item['leftover'] = {
493
+ 'offset': stream.tell(),
494
+ 'bytes': stream.read()
495
+ }
496
+ yield x
497
+
498
+
499
+ class DocInfo(ModelStream):
500
+
501
+ @property
502
+ def idmappings(self):
503
+ for model in self.models():
504
+ if model['type'] is IdMappings:
505
+ return model
506
+
507
+ @property
508
+ def facenames_by_lang(self):
509
+ facenames = list(m for m in self.models()
510
+ if m['type'] is FaceName)
511
+ languages = 'ko', 'en', 'cn', 'jp', 'other', 'symbol', 'user'
512
+ facenames_by_lang = dict()
513
+ offset = 0
514
+ for lang in languages:
515
+ n_fonts = self.idmappings['content'][lang + '_fonts']
516
+ facenames_by_lang[lang] = facenames[offset:offset + n_fonts]
517
+ offset += n_fonts
518
+ return facenames_by_lang
519
+
520
+ @property
521
+ def charshapes(self):
522
+ return (m for m in self.models()
523
+ if m['type'] is CharShape)
524
+
525
+ def get_charshape(self, charshape_id):
526
+ return nth(self.charshapes, charshape_id)
527
+
528
+ def charshape_lang_facename(self, charshape_id, lang):
529
+ charshape = self.get_charshape(charshape_id)
530
+ lang_facename_offset = charshape['content']['font_face'][lang]
531
+ return self.facenames_by_lang[lang][lang_facename_offset]
532
+
533
+
534
+ class Sections(recordstream.Sections):
535
+
536
+ section_class = ModelStream
537
+
538
+
539
+ class Hwp5File(recordstream.Hwp5File):
540
+
541
+ docinfo_class = DocInfo
542
+ bodytext_class = Sections
543
+
544
+
545
+ def create_context(file=None, **context):
546
+ if file is not None:
547
+ context['version'] = file.fileheader.version
548
+ assert 'version' in context
549
+ return context
src/hwp5/binmodel/_shared.py ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ import logging
24
+
25
+
26
+
27
+ from hwp5.dataio import StructType
28
+ from hwp5.dataio import Struct
29
+ from hwp5.dataio import Enum
30
+ from hwp5.dataio import Flags
31
+ from hwp5.dataio import PrimitiveType
32
+ from hwp5.dataio import UINT32
33
+ from hwp5.dataio import UINT16
34
+ from hwp5.dataio import UINT8
35
+ from hwp5.dataio import INT32
36
+ from hwp5.dataio import INT8
37
+ from hwp5.dataio import BYTE
38
+ from hwp5.dataio import HWPUNIT16
39
+ from hwp5.dataio import SHWPUNIT
40
+ from hwp5.dataio import N_ARRAY
41
+
42
+
43
+ logger = logging.getLogger(__name__)
44
+
45
+
46
+ tag_models = dict()
47
+
48
+
49
+ class RecordModelType(StructType):
50
+
51
+ def __new__(mcs, name, bases, attrs):
52
+ cls = StructType.__new__(mcs, name, bases, attrs)
53
+ if 'tagid' in attrs:
54
+ tagid = attrs['tagid']
55
+ assert tagid not in tag_models
56
+ tag_models[tagid] = cls
57
+ return cls
58
+
59
+
60
+ class RecordModel(object, metaclass=RecordModelType):
61
+ pass
62
+
63
+
64
+ class BinStorageId(UINT16):
65
+ pass
66
+
67
+
68
+ class COLORREF(int, metaclass=PrimitiveType):
69
+ binfmt = INT32.binfmt
70
+ never_instantiate = False
71
+
72
+ def __getattr__(self, name):
73
+ if name == 'r':
74
+ return self & 0xff
75
+ elif name == 'g':
76
+ return (self & 0xff00) >> 8
77
+ elif name == 'b':
78
+ return (self & 0xff0000) >> 16
79
+ elif name == 'a':
80
+ return int((self & 0xff000000) >> 24)
81
+ elif name == 'rgb':
82
+ return self.r, self.g, self.b
83
+
84
+ def __str__(self):
85
+ return '#%02x%02x%02x' % (self.r, self.g, self.b)
86
+
87
+ def __repr__(self):
88
+ class_name = self.__class__.__name__
89
+ value = '(0x%02x, 0x%02x, 0x%02x)' % self.rgb
90
+ return class_name + value
91
+
92
+
93
+ class Margin(Struct):
94
+ def attributes():
95
+ yield HWPUNIT16, 'left'
96
+ yield HWPUNIT16, 'right'
97
+ yield HWPUNIT16, 'top'
98
+ yield HWPUNIT16, 'bottom'
99
+ attributes = staticmethod(attributes)
100
+
101
+
102
+ class Coord(Struct):
103
+ def attributes():
104
+ yield SHWPUNIT, 'x'
105
+ yield SHWPUNIT, 'y'
106
+ attributes = staticmethod(attributes)
107
+
108
+
109
+ class Border(Struct):
110
+
111
+ # 표 20 테두리선 종류
112
+ StrokeEnum = Enum('none', 'solid',
113
+ 'dashed', 'dotted', 'dash-dot', 'dash-dot-dot',
114
+ 'long-dash', 'large-dot',
115
+ 'double', 'double-2', 'double-3', 'triple',
116
+ 'wave', 'double-wave',
117
+ 'inset', 'outset', 'groove', 'ridge')
118
+ StrokeType = Flags(UINT8,
119
+ 0, 4, StrokeEnum, 'stroke_type')
120
+
121
+ # 표 21 테두리선 굵기
122
+ widths = {'0.1mm': 0,
123
+ '0.12mm': 1,
124
+ '0.15mm': 2,
125
+ '0.2mm': 3,
126
+ '0.25mm': 4,
127
+ '0.3mm': 5,
128
+ '0.4mm': 6,
129
+ '0.5mm': 7,
130
+ '0.6mm': 8,
131
+ '0.7mm': 9,
132
+ '1.0mm': 10,
133
+ '1.5mm': 11,
134
+ '2.0mm': 12,
135
+ '3.0mm': 13,
136
+ '4.0mm': 14,
137
+ '5.0mm': 15}
138
+ WidthEnum = Enum(**widths)
139
+ Width = Flags(UINT8,
140
+ 0, 4, WidthEnum, 'width')
141
+
142
+ def attributes(cls):
143
+ yield cls.StrokeType, 'stroke_flags',
144
+ yield cls.Width, 'width_flags',
145
+ yield COLORREF, 'color',
146
+ attributes = classmethod(attributes)
147
+
148
+
149
+ class BorderLine(Struct):
150
+ ''' 표 81 테두리 선 정보 '''
151
+
152
+ LineEnd = Enum('round', 'flat')
153
+ ArrowShape = Enum('none', 'arrow', 'arrow2', 'diamond', 'circle', 'rect',
154
+ 'diamondfilled', 'disc', 'rectfilled')
155
+ ArrowSize = Enum('smallest', 'smaller', 'small', 'abitsmall', 'normal',
156
+ 'abitlarge', 'large', 'larger', 'largest')
157
+
158
+ ''' 표 82 테두리 선 정보 속성 '''
159
+ Flags = Flags(UINT32,
160
+ 0, 5, Border.StrokeEnum, 'stroke',
161
+ 6, 9, LineEnd, 'line_end',
162
+ 10, 15, ArrowShape, 'arrow_start',
163
+ 16, 21, ArrowShape, 'arrow_end',
164
+ 22, 25, ArrowSize, 'arrow_start_size',
165
+ 26, 29, ArrowSize, 'arrow_end_size',
166
+ 30, 'arrow_start_fill',
167
+ 31, 'arrow_end_fill')
168
+
169
+ def attributes(cls):
170
+ yield COLORREF, 'color'
171
+ yield INT32, 'width'
172
+ yield cls.Flags, 'flags'
173
+ attributes = classmethod(attributes)
174
+
175
+
176
+ class Fill(Struct):
177
+ pass
178
+
179
+
180
+ class FillNone(Fill):
181
+ def attributes():
182
+ yield UINT32, 'size', # SPEC is confusing
183
+ attributes = staticmethod(attributes)
184
+
185
+
186
+ class FillColorPattern(Fill):
187
+ ''' 표 23 채우기 정보 '''
188
+ PatternTypeEnum = Enum(NONE=255, HORIZONTAL=0, VERTICAL=1, BACKSLASH=2,
189
+ SLASH=3, GRID=4, CROSS=5)
190
+ PatternTypeFlags = Flags(UINT32,
191
+ 0, 7, PatternTypeEnum, 'pattern_type')
192
+
193
+ def attributes(cls):
194
+ yield COLORREF, 'background_color',
195
+ yield COLORREF, 'pattern_color',
196
+ yield cls.PatternTypeFlags, 'pattern_type_flags',
197
+ attributes = classmethod(attributes)
198
+
199
+
200
+ class FillImage(Fill):
201
+ FillImageEnum = Enum(TILE_ALL=0,
202
+ TILE_HORIZONTAL_TOP=1,
203
+ TILE_HORIZONTAL_BOTTOM=2,
204
+ TILE_VERTICAL_LEFT=3,
205
+ TILE_VERTICAL_RIGHT=4,
206
+ RESIZE=5,
207
+ CENTER=6,
208
+ CENTER_TOP=7,
209
+ CENTER_BOTTOM=8,
210
+ LEFT_MIDDLE=9,
211
+ LEFT_TOP=10,
212
+ LEFT_BOTTOM=11,
213
+ RIGHT_MIDDLE=12,
214
+ RIGHT_TOP=13,
215
+ RIGHT_BOTTOM=14,
216
+ NONE=15)
217
+ FillImageFlags = Flags(BYTE,
218
+ 0, 16, FillImageEnum, 'fillimage_type')
219
+
220
+ EffectEnum = Enum(REAL_PIC=0,
221
+ GRAY_SCALE=1,
222
+ BLACK_WHITE=2,
223
+ PATTERN8x8=3)
224
+ EffectFlags = Flags(UINT8,
225
+ 0, 8, EffectEnum, 'effect_type')
226
+
227
+ def attributes(cls):
228
+ yield cls.FillImageFlags, 'flags'
229
+ yield INT8, 'brightness'
230
+ yield INT8, 'contrast'
231
+ yield cls.EffectFlags, 'effect'
232
+ yield UINT16, 'bindata_id'
233
+ attributes = classmethod(attributes)
234
+
235
+
236
+ class Coord32(Struct):
237
+ def attributes():
238
+ yield UINT32, 'x'
239
+ yield UINT32, 'y'
240
+ attributes = staticmethod(attributes)
241
+
242
+
243
+ GradationTypeEnum = Enum(LINEAR=1, CIRCULAR=2, CONICAL=3, RECTANGULAR=4)
244
+ GradationTypeFlags = Flags(BYTE,
245
+ 0, 8, GradationTypeEnum, 'gradation_type')
246
+
247
+
248
+ class FillGradation(Fill):
249
+ def attributes():
250
+ yield GradationTypeFlags, 'type',
251
+ yield UINT32, 'shear', # 기울임 각 (도)
252
+ yield Coord32, 'center',
253
+ yield UINT32, 'blur', # 번짐 정도: 0-100
254
+ # TODO: 스펙 1.2에 따르면 색상 수 > 2인 경우
255
+ # 색상이 바뀌는 위치 배열이 온다고 함
256
+ yield N_ARRAY(UINT32, COLORREF), 'colors',
257
+ attributes = staticmethod(attributes)
258
+
259
+
260
+ def ref_parent_member(member_name):
261
+ def f(context, values):
262
+ context, model = context['parent']
263
+ return model['content'][member_name]
264
+ f.__doc__ = 'PARENTREC.' + member_name
265
+ return f
src/hwp5/binmodel/controlchar.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+ import re
23
+ import sys
24
+
25
+
26
+
27
+ from hwp5.dataio import PrimitiveType
28
+ from hwp5.dataio import UINT32
29
+ from hwp5.dataio import UINT16
30
+ from hwp5.dataio import UINT8
31
+
32
+
33
+ PY3 = sys.version_info.major == 3
34
+ if PY3:
35
+ unichr = chr
36
+
37
+
38
+ class CHID(str, metaclass=PrimitiveType):
39
+
40
+ fixed_size = 4
41
+
42
+ # Common controls
43
+ GSO = 'gso '
44
+ TBL = 'tbl '
45
+ LINE = '$lin'
46
+ RECT = '$rec'
47
+ ELLI = '$ell'
48
+ ARC = '$arc'
49
+ POLY = '$pol'
50
+ CURV = '$cur'
51
+ EQED = 'eqed'
52
+ PICT = '$pic'
53
+ OLE = '$ole'
54
+ CONTAINER = '$con'
55
+
56
+ # Controls
57
+ SECD = 'secd'
58
+ COLD = 'cold'
59
+ HEADER = 'head'
60
+ FOOTER = 'foot'
61
+ FN = 'fn '
62
+ EN = 'en '
63
+ ATNO = 'atno'
64
+ NWNO = 'nwno'
65
+ PGHD = 'pghd'
66
+ PGCT = 'pgct'
67
+ PGNP = 'pgnp'
68
+ IDXM = 'idxm'
69
+ BOKM = 'bokm'
70
+ TCPS = 'tcps'
71
+ TDUT = 'tdut'
72
+ TCMT = 'tcmt'
73
+
74
+ # Field starts
75
+ FIELD_UNK = '%unk'
76
+ FIELD_DTE = '%dte'
77
+ FIELD_DDT = '%ddt'
78
+ FIELD_PAT = '%pat'
79
+ FIELD_BMK = '%bmk'
80
+ FIELD_MMG = '%mmg'
81
+ FIELD_XRF = '%xrf'
82
+ FIELD_FMU = '%fmu'
83
+ FIELD_CLK = '%clk'
84
+ FIELD_SMR = '%smr'
85
+ FIELD_USR = '%usr'
86
+ FIELD_HLK = '%hlk'
87
+ FIELD_REVISION_SIGN = '%sig'
88
+ FIELD_REVISION_DELETE = '%%*d'
89
+ FIELD_REVISION_ATTACH = '%%*a'
90
+ FIELD_REVISION_CLIPPING = '%%*C'
91
+ FIELD_REVISION_SAWTOOTH = '%%*S'
92
+ FIELD_REVISION_THINKING = '%%*T'
93
+ FIELD_REVISION_PRAISE = '%%*P'
94
+ FIELD_REVISION_LINE = '%%*L'
95
+ FIELD_REVISION_SIMPLECHANGE = '%%*c'
96
+ FIELD_REVISION_HYPERLINK = '%%*h'
97
+ FIELD_REVISION_LINEATTACH = '%%*A'
98
+ FIELD_REVISION_LINELINK = '%%*i'
99
+ FIELD_REVISION_LINETRANSFER = '%%*t'
100
+ FIELD_REVISION_RIGHTMOVE = '%%*r'
101
+ FIELD_REVISION_LEFTMOVE = '%%*l'
102
+ FIELD_REVISION_TRANSFER = '%%*n'
103
+ FIELD_REVISION_SIMPLEINSERT = '%%*e'
104
+ FIELD_REVISION_SPLIT = '%spl'
105
+ FIELD_REVISION_CHANGE = '%%mr'
106
+ FIELD_MEMO = '%%me'
107
+ FIELD_PRIVATE_INFO_SECURITY = '%cpr'
108
+
109
+ def decode(bytes, context=None):
110
+ if PY3:
111
+ return (
112
+ chr(bytes[3]) +
113
+ chr(bytes[2]) +
114
+ chr(bytes[1]) +
115
+ chr(bytes[0])
116
+ )
117
+ else:
118
+ return bytes[3] + bytes[2] + bytes[1] + bytes[0]
119
+ decode = staticmethod(decode)
120
+
121
+
122
+ class ControlChar(object):
123
+ class CHAR(object):
124
+ size = 1
125
+
126
+ class INLINE(object):
127
+ size = 8
128
+
129
+ class EXTENDED(object):
130
+ size = 8
131
+ chars = {0x00: ('NULL', CHAR),
132
+ 0x01: ('CTLCHR01', EXTENDED),
133
+ 0x02: ('SECTION_COLUMN_DEF', EXTENDED),
134
+ 0x03: ('FIELD_START', EXTENDED),
135
+ 0x04: ('FIELD_END', INLINE),
136
+ 0x05: ('CTLCHR05', INLINE),
137
+ 0x06: ('CTLCHR06', INLINE),
138
+ 0x07: ('CTLCHR07', INLINE),
139
+ 0x08: ('TITLE_MARK', INLINE),
140
+ 0x09: ('TAB', INLINE),
141
+ 0x0a: ('LINE_BREAK', CHAR),
142
+ 0x0b: ('DRAWING_TABLE_OBJECT', EXTENDED),
143
+ 0x0c: ('CTLCHR0C', EXTENDED),
144
+ 0x0d: ('PARAGRAPH_BREAK', CHAR),
145
+ 0x0e: ('CTLCHR0E', EXTENDED),
146
+ 0x0f: ('HIDDEN_EXPLANATION', EXTENDED),
147
+ 0x10: ('HEADER_FOOTER', EXTENDED),
148
+ 0x11: ('FOOT_END_NOTE', EXTENDED),
149
+ 0x12: ('AUTO_NUMBER', EXTENDED),
150
+ 0x13: ('CTLCHR13', INLINE),
151
+ 0x14: ('CTLCHR14', INLINE),
152
+ 0x15: ('PAGE_CTLCHR', EXTENDED),
153
+ 0x16: ('BOOKMARK', EXTENDED),
154
+ 0x17: ('CTLCHR17', EXTENDED),
155
+ 0x18: ('HYPHEN', CHAR),
156
+ 0x1e: ('NONBREAK_SPACE', CHAR),
157
+ 0x1f: ('FIXWIDTH_SPACE', CHAR)}
158
+ names = dict((unichr(code), name) for code, (name, kind) in chars.items())
159
+ kinds = dict((unichr(code), kind) for code, (name, kind) in chars.items())
160
+
161
+ def _populate(cls):
162
+ for ch, name in cls.names.items():
163
+ setattr(cls, name, ch)
164
+ _populate = classmethod(_populate)
165
+ REGEX_CONTROL_CHAR = re.compile(b'[\x00-\x1f]\x00')
166
+
167
+ def find(cls, data, start_idx):
168
+ while True:
169
+ m = cls.REGEX_CONTROL_CHAR.search(data, start_idx)
170
+ if m is not None:
171
+ i = m.start()
172
+ if i & 1 == 1:
173
+ start_idx = i + 1
174
+ continue
175
+ if PY3:
176
+ char = unichr(data[i])
177
+ else:
178
+ char = unichr(ord(data[i]))
179
+ size = cls.kinds[char].size
180
+ return i, i + (size * 2)
181
+ data_len = len(data)
182
+ return data_len, data_len
183
+ find = classmethod(find)
184
+
185
+ def decode(cls, bytes):
186
+ code = UINT16.decode(bytes[0:2])
187
+ ch = unichr(code)
188
+ if cls.kinds[ch].size == 8:
189
+ bytes = bytes[2:2 + 12]
190
+ if ch == ControlChar.TAB:
191
+ param = dict(width=UINT32.decode(bytes[0:4]),
192
+ unknown0=UINT8.decode(bytes[4:5]),
193
+ unknown1=UINT8.decode(bytes[5:6]),
194
+ unknown2=bytes[6:])
195
+ return dict(code=code, param=param)
196
+ else:
197
+ chid = CHID.decode(bytes[0:4])
198
+ param = bytes[4:12]
199
+ return dict(code=code, chid=chid, param=param)
200
+ else:
201
+ return dict(code=code)
202
+ decode = classmethod(decode)
203
+
204
+ def get_kind_by_code(cls, code):
205
+ ch = unichr(code)
206
+ return cls.kinds[ch]
207
+ get_kind_by_code = classmethod(get_kind_by_code)
208
+
209
+ def get_name_by_code(cls, code):
210
+ ch = unichr(code)
211
+ return cls.names.get(ch, 'CTLCHR%02x' % code)
212
+ get_name_by_code = classmethod(get_name_by_code)
213
+
214
+
215
+ ControlChar._populate()
src/hwp5/binmodel/controls/__init__.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controls.bookmark_control import BookmarkControl
24
+ from hwp5.binmodel.controls.columns_def import ColumnsDef
25
+ from hwp5.binmodel.controls.common_controls import CommonControl
26
+ from hwp5.binmodel.controls.dutmal import Dutmal
27
+ from hwp5.binmodel.controls.field import Field
28
+ from hwp5.binmodel.controls.field import FieldUnknown
29
+ from hwp5.binmodel.controls.field import FieldDate
30
+ from hwp5.binmodel.controls.field import FieldDocDate
31
+ from hwp5.binmodel.controls.field import FieldPath
32
+ from hwp5.binmodel.controls.field import FieldBookmark
33
+ from hwp5.binmodel.controls.field import FieldMailMerge
34
+ from hwp5.binmodel.controls.field import FieldCrossRef
35
+ from hwp5.binmodel.controls.field import FieldFormula
36
+ from hwp5.binmodel.controls.field import FieldClickHere
37
+ from hwp5.binmodel.controls.field import FieldClickHereData
38
+ from hwp5.binmodel.controls.field import FieldSummary
39
+ from hwp5.binmodel.controls.field import FieldUserInfo
40
+ from hwp5.binmodel.controls.field import FieldHyperLink
41
+ from hwp5.binmodel.controls.field import FieldMemo
42
+ from hwp5.binmodel.controls.field import FieldPrivateInfoSecurity
43
+ from hwp5.binmodel.controls.gshape_object_control import GShapeObjectControl
44
+ from hwp5.binmodel.controls.header_footer import HeaderFooter
45
+ from hwp5.binmodel.controls.hidden_comment import HiddenComment
46
+ from hwp5.binmodel.controls.index_marker import IndexMarker
47
+ from hwp5.binmodel.controls.note import Note
48
+ from hwp5.binmodel.controls.note import FootNote
49
+ from hwp5.binmodel.controls.note import EndNote
50
+ from hwp5.binmodel.controls.numbering import AutoNumbering
51
+ from hwp5.binmodel.controls.numbering import NewNumbering
52
+ from hwp5.binmodel.controls.page_hide import PageHide
53
+ from hwp5.binmodel.controls.page_number_position import PageNumberPosition
54
+ from hwp5.binmodel.controls.page_odd_even import PageOddEven
55
+ from hwp5.binmodel.controls.section_def import SectionDef
56
+ from hwp5.binmodel.controls.table_control import TableControl
57
+ from hwp5.binmodel.controls.tcps_control import TCPSControl
58
+
59
+ # suppress pyflake8 warning 'imported but not used'
60
+ BookmarkControl
61
+ ColumnsDef
62
+ CommonControl
63
+ Dutmal
64
+ Field
65
+ FieldUnknown
66
+ FieldDate
67
+ FieldDocDate
68
+ FieldPath
69
+ FieldBookmark
70
+ FieldMailMerge
71
+ FieldCrossRef
72
+ FieldFormula
73
+ FieldClickHere
74
+ FieldClickHereData
75
+ FieldSummary
76
+ FieldUserInfo
77
+ FieldHyperLink
78
+ FieldMemo
79
+ FieldPrivateInfoSecurity
80
+ GShapeObjectControl
81
+ HeaderFooter
82
+ HiddenComment
83
+ IndexMarker
84
+ Note
85
+ FootNote
86
+ EndNote
87
+ AutoNumbering
88
+ NewNumbering
89
+ PageHide
90
+ PageNumberPosition
91
+ PageOddEven
92
+ SectionDef
93
+ TableControl
94
+ TCPSControl
src/hwp5/binmodel/controls/_shared.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+
24
+
25
+ from hwp5.binmodel._shared import RecordModelType
26
+ from hwp5.binmodel._shared import RecordModel
27
+ from hwp5.tagids import HWPTAG_CTRL_HEADER
28
+ from hwp5.binmodel.controlchar import CHID
29
+
30
+
31
+ control_models = dict()
32
+
33
+
34
+ class ControlType(RecordModelType):
35
+
36
+ def __new__(mcs, name, bases, attrs):
37
+ cls = RecordModelType.__new__(mcs, name, bases, attrs)
38
+ if 'chid' in attrs:
39
+ chid = attrs['chid']
40
+ assert chid not in control_models
41
+ control_models[chid] = cls
42
+ return cls
43
+
44
+
45
+ class Control(RecordModel, metaclass=ControlType):
46
+ ''' 4.2.6. 컨트롤 헤더 '''
47
+
48
+ tagid = HWPTAG_CTRL_HEADER
49
+
50
+ def attributes():
51
+ yield CHID, 'chid'
52
+ attributes = staticmethod(attributes)
53
+
54
+ extension_types = control_models
55
+
56
+ def get_extension_key(cls, context, model):
57
+ ''' chid '''
58
+ return model['content']['chid']
59
+ get_extension_key = classmethod(get_extension_key)
src/hwp5/binmodel/controls/bookmark_control.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import UINT32
25
+ from hwp5.dataio import UINT16
26
+ from hwp5.dataio import BSTR
27
+ from hwp5.binmodel.tagid71_ctrl_data import ControlData
28
+ from hwp5.binmodel.controls._shared import Control
29
+
30
+
31
+ class BookmarkControl(Control):
32
+ ''' 4.2.10.11. 책갈피 '''
33
+ chid = CHID.BOKM
34
+
35
+ def attributes():
36
+ if False:
37
+ yield
38
+ attributes = staticmethod(attributes)
39
+
40
+
41
+ class BookmarkControlData(ControlData):
42
+
43
+ parent_model_type = BookmarkControl
44
+
45
+ def attributes():
46
+ yield UINT32, 'unknown1'
47
+ yield UINT32, 'unknown2'
48
+ yield UINT16, 'unknown3'
49
+ yield BSTR, 'name'
50
+ attributes = staticmethod(attributes)
src/hwp5/binmodel/controls/columns_def.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import Enum
25
+ from hwp5.dataio import Flags
26
+ from hwp5.dataio import Struct
27
+ from hwp5.dataio import UINT16
28
+ from hwp5.dataio import WORD
29
+ from hwp5.dataio import HWPUNIT16
30
+ from hwp5.dataio import X_ARRAY
31
+ from hwp5.dataio import ref_member_flag
32
+ from hwp5.binmodel.controls._shared import Control
33
+ from hwp5.binmodel._shared import Border
34
+
35
+
36
+ class Column0(Struct):
37
+
38
+ @staticmethod
39
+ def attributes():
40
+ yield WORD, 'width'
41
+
42
+
43
+ class Column(Struct):
44
+ @staticmethod
45
+ def attributes():
46
+ yield WORD, 'spacing'
47
+ yield WORD, 'width'
48
+
49
+
50
+ class ColumnsDef(Control):
51
+ ''' 4.2.10.2. 단 정의 '''
52
+ chid = CHID.COLD
53
+
54
+ Kind = Enum('normal', 'distribute', 'parallel')
55
+ Direction = Enum('l2r', 'r2l', 'both')
56
+ Flags = Flags(UINT16,
57
+ 0, 1, Kind, 'kind',
58
+ 2, 9, 'count',
59
+ 10, 11, Direction, 'direction',
60
+ 12, 'same_widths')
61
+
62
+ def attributes(cls):
63
+ yield cls.Flags, 'flags'
64
+ yield HWPUNIT16, 'spacing'
65
+
66
+ def not_same_widths(context, values):
67
+ ''' flags.same_widths == 0 '''
68
+ return not values['flags'].same_widths
69
+
70
+ def n_entries(member_ref):
71
+ def n_entries(context, values):
72
+ n_columns = member_ref(context, values)
73
+ return n_columns - 1
74
+ return n_entries
75
+
76
+ yield dict(name='column0', type=Column0,
77
+ condition=not_same_widths)
78
+ yield dict(name='columns',
79
+ type=X_ARRAY(Column,
80
+ n_entries(ref_member_flag('flags', 'count'))),
81
+ condition=not_same_widths)
82
+ yield UINT16, 'attr2'
83
+ yield Border, 'splitter'
84
+ attributes = classmethod(attributes)
src/hwp5/binmodel/controls/common_controls.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controls._shared import Control
24
+ from hwp5.dataio import Enum
25
+ from hwp5.dataio import Flags
26
+ from hwp5.dataio import UINT32
27
+ from hwp5.dataio import SHWPUNIT
28
+ from hwp5.dataio import HWPUNIT
29
+ from hwp5.dataio import INT16
30
+ from hwp5.dataio import BSTR
31
+ from hwp5.binmodel._shared import Margin
32
+
33
+
34
+ class CommonControl(Control):
35
+
36
+ # 표 65 개체 공통 속성의 속성
37
+ Flow = Enum(FLOAT=0, BLOCK=1, BACK=2, FRONT=3)
38
+ TextSide = Enum(BOTH=0, LEFT=1, RIGHT=2, LARGER=3)
39
+ VRelTo = Enum(PAPER=0, PAGE=1, PARAGRAPH=2)
40
+ HRelTo = Enum(PAPER=0, PAGE=1, COLUMN=2, PARAGRAPH=3)
41
+ VAlign = Enum(TOP=0, MIDDLE=1, BOTTOM=2)
42
+ HAlign = Enum(LEFT=0, CENTER=1, RIGHT=2, INSIDE=3, OUTSIDE=4)
43
+ WidthRelTo = Enum(PAPER=0, PAGE=1, COLUMN=2, PARAGRAPH=3, ABSOLUTE=4)
44
+ HeightRelTo = Enum(PAPER=0, PAGE=1, ABSOLUTE=2)
45
+ NumberCategory = Enum(NONE=0, FIGURE=1, TABLE=2, EQUATION=3)
46
+
47
+ CommonControlFlags = Flags(UINT32,
48
+ 0, 'inline',
49
+ 2, 'affect_line_spacing',
50
+ 3, 4, VRelTo, 'vrelto',
51
+ 5, 7, VAlign, 'valign',
52
+ 8, 9, HRelTo, 'hrelto',
53
+ 10, 12, HAlign, 'halign',
54
+ 13, 'restrict_in_page',
55
+ 14, 'overlap_others',
56
+ 15, 17, WidthRelTo, 'width_relto',
57
+ 18, 19, HeightRelTo, 'height_relto',
58
+ 20, 'protect_size_when_vrelto_paragraph',
59
+ 21, 23, Flow, 'flow',
60
+ 24, 25, TextSide, 'text_side',
61
+ 26, 27, NumberCategory, 'number_category')
62
+
63
+ MARGIN_LEFT = 0
64
+ MARGIN_RIGHT = 1
65
+ MARGIN_TOP = 2
66
+ MARGIN_BOTTOM = 3
67
+
68
+ def attributes(cls):
69
+ ''' 표 64 개체 공통 속성 '''
70
+ yield cls.CommonControlFlags, 'flags',
71
+ yield SHWPUNIT, 'y', # DIFFSPEC
72
+ yield SHWPUNIT, 'x', # DIFFSPEC
73
+ yield HWPUNIT, 'width',
74
+ yield HWPUNIT, 'height',
75
+ yield INT16, 'z_order',
76
+ yield INT16, 'unknown1',
77
+ yield Margin, 'margin',
78
+ yield UINT32, 'instance_id',
79
+ yield dict(type=INT16, name='unknown2', version=(5, 0, 0, 5))
80
+ yield dict(type=BSTR, name='description', version=(5, 0, 0, 5))
81
+ attributes = classmethod(attributes)
src/hwp5/binmodel/controls/dutmal.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import Enum
25
+ from hwp5.dataio import Flags
26
+ from hwp5.dataio import UINT32
27
+ from hwp5.dataio import BSTR
28
+ from hwp5.binmodel.controls._shared import Control
29
+
30
+
31
+ class Dutmal(Control):
32
+ ''' 4.2.10.13. 덧말 '''
33
+ chid = CHID.TDUT
34
+ Position = Enum(ABOVE=0, BELOW=1, CENTER=2)
35
+ Align = Enum(BOTH=0, LEFT=1, RIGHT=2, CENTER=3, DISTRIBUTE=4,
36
+ DISTRIBUTE_SPACE=5)
37
+
38
+ def attributes(cls):
39
+ yield BSTR, 'maintext'
40
+ yield BSTR, 'subtext'
41
+ yield Flags(UINT32,
42
+ 0, 31, cls.Position, 'position'), 'position-flags'
43
+ yield UINT32, 'fsizeratio'
44
+ yield UINT32, 'option'
45
+ yield UINT32, 'stylenumber'
46
+ yield Flags(UINT32,
47
+ 0, 31, cls.Align, 'align'), 'align-flags'
48
+ attributes = classmethod(attributes)
src/hwp5/binmodel/controls/field.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import Flags
25
+ from hwp5.dataio import UINT32
26
+ from hwp5.dataio import BSTR
27
+ from hwp5.dataio import BYTE
28
+ from hwp5.binmodel.tagid71_ctrl_data import ControlData
29
+ from hwp5.binmodel.controls._shared import Control
30
+
31
+
32
+ class Field(Control):
33
+ ''' 4.2.10.15 필드 시작 '''
34
+
35
+ Flags = Flags(UINT32,
36
+ 0, 'editableInReadOnly',
37
+ 11, 14, 'visitedType',
38
+ 15, 'modified')
39
+
40
+ def attributes(cls):
41
+ yield cls.Flags, 'flags',
42
+ yield BYTE, 'extra_attr',
43
+ yield BSTR, 'command',
44
+ yield UINT32, 'id',
45
+ attributes = classmethod(attributes)
46
+
47
+
48
+ class FieldUnknown(Field):
49
+ chid = CHID.FIELD_UNK
50
+
51
+
52
+ class FieldDate(Field):
53
+ chid = CHID.FIELD_DTE
54
+
55
+
56
+ class FieldDocDate(Field):
57
+ chid = CHID.FIELD_DDT
58
+
59
+
60
+ class FieldPath(Field):
61
+ chid = CHID.FIELD_PAT
62
+
63
+
64
+ class FieldBookmark(Field):
65
+ chid = CHID.FIELD_BMK
66
+
67
+
68
+ class FieldMailMerge(Field):
69
+ chid = CHID.FIELD_MMG
70
+
71
+
72
+ class FieldCrossRef(Field):
73
+ chid = CHID.FIELD_XRF
74
+
75
+
76
+ class FieldFormula(Field):
77
+ chid = CHID.FIELD_FMU
78
+
79
+
80
+ class FieldClickHere(Field):
81
+ chid = CHID.FIELD_CLK
82
+
83
+
84
+ class FieldClickHereData(ControlData):
85
+ parent_model_type = FieldClickHere
86
+
87
+
88
+ class FieldSummary(Field):
89
+ chid = CHID.FIELD_SMR
90
+
91
+
92
+ class FieldUserInfo(Field):
93
+ chid = CHID.FIELD_USR
94
+
95
+
96
+ class FieldHyperLink(Field):
97
+ chid = CHID.FIELD_HLK
98
+
99
+ def geturl(self):
100
+ s = self.command.split(';')
101
+ return s[0].replace('\\:', ':')
102
+
103
+
104
+ class FieldRevisionSign(Field):
105
+ chid = CHID.FIELD_REVISION_SIGN
106
+
107
+
108
+ class FieldRevisionDelete(Field):
109
+ chid = CHID.FIELD_REVISION_DELETE
110
+
111
+
112
+ class FieldRevisionAttach(Field):
113
+ chid = CHID.FIELD_REVISION_ATTACH
114
+
115
+
116
+ class FieldRevisionClipping(Field):
117
+ chid = CHID.FIELD_REVISION_CLIPPING
118
+
119
+
120
+ class FieldRevisionSawtooth(Field):
121
+ chid = CHID.FIELD_REVISION_SAWTOOTH
122
+
123
+
124
+ class FieldRevisionThinking(Field):
125
+ chid = CHID.FIELD_REVISION_THINKING
126
+
127
+
128
+ class FieldRevisionPraise(Field):
129
+ chid = CHID.FIELD_REVISION_PRAISE
130
+
131
+
132
+ class FieldRevisionLine(Field):
133
+ chid = CHID.FIELD_REVISION_LINE
134
+
135
+
136
+ class FieldRevisionSimpleChange(Field):
137
+ chid = CHID.FIELD_REVISION_SIMPLECHANGE
138
+
139
+
140
+ class FieldRevisionHyperlink(Field):
141
+ chid = CHID.FIELD_REVISION_HYPERLINK
142
+
143
+
144
+ class FieldRevisionLineAttach(Field):
145
+ chid = CHID.FIELD_REVISION_LINEATTACH
146
+
147
+
148
+ class FieldRevisionLineLink(Field):
149
+ chid = CHID.FIELD_REVISION_LINELINK
150
+
151
+
152
+ class FieldRevisionLineTransfer(Field):
153
+ chid = CHID.FIELD_REVISION_LINETRANSFER
154
+
155
+
156
+ class FieldRevisionRightMove(Field):
157
+ chid = CHID.FIELD_REVISION_RIGHTMOVE
158
+
159
+
160
+ class FieldRevisionLeftMove(Field):
161
+ chid = CHID.FIELD_REVISION_LEFTMOVE
162
+
163
+
164
+ class FieldRevisionTransfer(Field):
165
+ chid = CHID.FIELD_REVISION_TRANSFER
166
+
167
+
168
+ class FieldRevisionSimpleInsert(Field):
169
+ chid = CHID.FIELD_REVISION_SIMPLEINSERT
170
+
171
+
172
+ class FieldRevisionSplit(Field):
173
+ chid = CHID.FIELD_REVISION_SPLIT
174
+
175
+
176
+ class FieldRevisionChange(Field):
177
+ chid = CHID.FIELD_REVISION_CHANGE
178
+
179
+
180
+ class FieldMemo(Field):
181
+ chid = CHID.FIELD_MEMO
182
+
183
+
184
+ class FieldPrivateInfoSecurity(Field):
185
+ chid = CHID.FIELD_PRIVATE_INFO_SECURITY
src/hwp5/binmodel/controls/gshape_object_control.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controls.common_controls import CommonControl
24
+ from hwp5.binmodel.controlchar import CHID
25
+
26
+
27
+ class GShapeObjectControl(CommonControl):
28
+ chid = CHID.GSO
src/hwp5/binmodel/controls/header_footer.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import Enum
25
+ from hwp5.dataio import Flags
26
+ from hwp5.dataio import UINT32
27
+ from hwp5.binmodel.controls._shared import Control
28
+
29
+
30
+ class HeaderFooter(Control):
31
+ ''' 4.2.10.3. 머리말/꼬리말 '''
32
+ Places = Enum(BOTH_PAGES=0, EVEN_PAGE=1, ODD_PAGE=2)
33
+ Flags = Flags(UINT32,
34
+ 0, 1, Places, 'places')
35
+
36
+ def attributes(cls):
37
+ yield cls.Flags, 'flags'
38
+ attributes = classmethod(attributes)
39
+
40
+
41
+ class Header(HeaderFooter):
42
+ ''' 머리말 '''
43
+ chid = CHID.HEADER
44
+
45
+
46
+ class Footer(HeaderFooter):
47
+ ''' 꼬리말 '''
48
+ chid = CHID.FOOTER
src/hwp5/binmodel/controls/hidden_comment.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.binmodel.controls._shared import Control
25
+
26
+
27
+ class HiddenComment(Control):
28
+ ''' 4.2.10.14 숨은 설명 '''
29
+ chid = CHID.TCMT
30
+
31
+ def attributes():
32
+ if False:
33
+ yield
34
+ attributes = staticmethod(attributes)
src/hwp5/binmodel/controls/index_marker.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import UINT16
25
+ from hwp5.dataio import BSTR
26
+ from hwp5.binmodel.controls._shared import Control
27
+
28
+
29
+ class IndexMarker(Control):
30
+ ''' 4.2.10.10. 찾아보기 표식 '''
31
+ chid = CHID.IDXM
32
+
33
+ def attributes():
34
+ yield BSTR, 'keyword1'
35
+ yield BSTR, 'keyword2'
36
+ yield UINT16, 'dummy'
37
+ attributes = staticmethod(attributes)
src/hwp5/binmodel/controls/note.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import UINT32
25
+ from hwp5.dataio import UINT16
26
+ from hwp5.binmodel.controls._shared import Control
27
+
28
+
29
+ class Note(Control):
30
+ ''' 4.2.10.4 미주/각주 '''
31
+ def attributes():
32
+ yield UINT32, 'number'
33
+ yield UINT32, 'unknown0'
34
+ yield UINT32, 'unknown1'
35
+ yield dict(type=UINT16, name='unknown2', version=(5, 0, 3, 0))
36
+ yield dict(type=UINT16, name='unknown3', version=(5, 0, 3, 0))
37
+ attributes = staticmethod(attributes)
38
+
39
+
40
+ class FootNote(Note):
41
+ ''' 각주 '''
42
+ chid = CHID.FN
43
+
44
+
45
+ class EndNote(Note):
46
+ ''' 미주 '''
47
+ chid = CHID.EN
src/hwp5/binmodel/controls/numbering.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import Enum
25
+ from hwp5.dataio import Flags
26
+ from hwp5.dataio import UINT32
27
+ from hwp5.dataio import UINT16
28
+ from hwp5.dataio import WCHAR
29
+ from hwp5.binmodel.controls._shared import Control
30
+
31
+
32
+ class NumberingControl(Control):
33
+ Kind = Enum(
34
+ PAGE=0, FOOTNOTE=1, ENDNOTE=2, PICTURE=3, TABLE=4, EQUATION=5,
35
+ UNKNOWN6=6,
36
+ )
37
+ Flags = Flags(UINT32,
38
+ 0, 3, Kind, 'kind',
39
+ 4, 11, 'footnoteshape',
40
+ 12, 'superscript')
41
+
42
+ def attributes(cls):
43
+ yield cls.Flags, 'flags',
44
+ yield UINT16, 'number',
45
+ attributes = classmethod(attributes)
46
+
47
+
48
+ class AutoNumbering(NumberingControl):
49
+ ''' 4.2.10.5. 자동 번호 '''
50
+ chid = CHID.ATNO
51
+
52
+ def attributes(cls):
53
+ yield WCHAR, 'usersymbol',
54
+ yield WCHAR, 'prefix',
55
+ yield WCHAR, 'suffix',
56
+ attributes = classmethod(attributes)
57
+
58
+ def __unicode__(self):
59
+ prefix = u''
60
+ suffix = u''
61
+ if self.flags.kind == self.Kind.FOOTNOTE:
62
+ if self.suffix != u'\x00':
63
+ suffix = self.suffix
64
+ return prefix + unicode(self.number) + suffix
65
+
66
+
67
+ class NewNumbering(NumberingControl):
68
+ ''' 4.2.10.6. 새 번호 지정 '''
69
+ chid = CHID.NWNO
src/hwp5/binmodel/controls/page_hide.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import Flags
25
+ from hwp5.dataio import UINT32
26
+ from hwp5.binmodel.controls._shared import Control
27
+
28
+
29
+ class PageHide(Control):
30
+ ''' 4.2.10.7 감추기 '''
31
+ chid = CHID.PGHD
32
+ Flags = Flags(UINT32,
33
+ 0, 'header',
34
+ 1, 'footer',
35
+ 2, 'basepage',
36
+ 3, 'pageborder',
37
+ 4, 'pagefill',
38
+ 5, 'pagenumber')
39
+
40
+ def attributes(cls):
41
+ yield cls.Flags, 'flags'
42
+ attributes = classmethod(attributes)
src/hwp5/binmodel/controls/page_number_position.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import Enum
25
+ from hwp5.dataio import Flags
26
+ from hwp5.dataio import UINT32
27
+ from hwp5.dataio import WCHAR
28
+ from hwp5.binmodel.controls._shared import Control
29
+
30
+
31
+ class PageNumberPosition(Control):
32
+ ''' 4.2.10.9. 쪽 번호 위치 '''
33
+ chid = CHID.PGNP
34
+ Position = Enum(NONE=0,
35
+ TOP_LEFT=1, TOP_CENTER=2, TOP_RIGHT=3,
36
+ BOTTOM_LEFT=4, BOTTOM_CENTER=5, BOTTOM_RIGHT=6,
37
+ OUTSIDE_TOP=7, OUTSIDE_BOTTOM=8,
38
+ INSIDE_TOP=9, INSIDE_BOTTOM=10)
39
+ Flags = Flags(UINT32,
40
+ 0, 7, 'shape',
41
+ 8, 11, Position, 'position')
42
+
43
+ def attributes(cls):
44
+ yield cls.Flags, 'flags'
45
+ yield WCHAR, 'usersymbol'
46
+ yield WCHAR, 'prefix'
47
+ yield WCHAR, 'suffix'
48
+ yield WCHAR, 'dash'
49
+ attributes = classmethod(attributes)
src/hwp5/binmodel/controls/page_odd_even.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import Enum
25
+ from hwp5.dataio import Flags
26
+ from hwp5.dataio import UINT32
27
+ from hwp5.binmodel.controls._shared import Control
28
+
29
+
30
+ class PageOddEven(Control):
31
+ ''' 4.2.10.8 홀/짝수 조정 '''
32
+ chid = CHID.PGCT
33
+ OddEven = Enum(BOTH_PAGES=0, EVEN_PAGE=1, ODD_PAGE=2)
34
+ Flags = Flags(UINT32,
35
+ 0, 1, OddEven, 'pages')
36
+
37
+ def attributes(cls):
38
+ yield cls.Flags, 'flags'
39
+ attributes = classmethod(attributes)
src/hwp5/binmodel/controls/section_def.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import Flags
25
+ from hwp5.dataio import UINT32
26
+ from hwp5.dataio import UINT16
27
+ from hwp5.dataio import HWPUNIT
28
+ from hwp5.dataio import HWPUNIT16
29
+ from hwp5.dataio import HexBytes
30
+ from hwp5.binmodel.tagid71_ctrl_data import ControlData
31
+ from hwp5.binmodel.controls._shared import Control
32
+
33
+
34
+ class SectionDef(Control):
35
+ ''' 4.2.10.1. 구역 정의 '''
36
+ chid = CHID.SECD
37
+
38
+ Flags = Flags(UINT32,
39
+ 0, 'hide_header',
40
+ 1, 'hide_footer',
41
+ 2, 'hide_page',
42
+ 3, 'hide_border',
43
+ 4, 'hide_background',
44
+ 5, 'hide_pagenumber',
45
+ 8, 'show_border_on_first_page_only',
46
+ 9, 'show_background_on_first_page_only',
47
+ 16, 18, 'text_direction',
48
+ 19, 'hide_blank_line',
49
+ 20, 21, 'pagenum_on_split_section',
50
+ 22, 'squared_manuscript_paper')
51
+
52
+ def attributes(cls):
53
+ yield cls.Flags, 'flags',
54
+ yield HWPUNIT16, 'columnspacing',
55
+ yield HWPUNIT16, 'grid_vertical',
56
+ yield HWPUNIT16, 'grid_horizontal',
57
+ yield HWPUNIT, 'defaultTabStops',
58
+ yield UINT16, 'numbering_shape_id',
59
+ yield UINT16, 'starting_pagenum',
60
+ yield UINT16, 'starting_picturenum',
61
+ yield UINT16, 'starting_tablenum',
62
+ yield UINT16, 'starting_equationnum',
63
+ yield dict(type=UINT32, name='unknown1', version=(5, 0, 1, 7))
64
+ yield dict(type=UINT32, name='unknown2', version=(5, 0, 1, 7))
65
+ attributes = classmethod(attributes)
66
+
67
+
68
+ class SectionDefData(ControlData):
69
+ parent_model_type = SectionDef
70
+
71
+ def attributes():
72
+ yield HexBytes(280), 'unknown'
73
+ attributes = staticmethod(attributes)
src/hwp5/binmodel/controls/table_control.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controls.common_controls import CommonControl
24
+ from hwp5.binmodel.controlchar import CHID
25
+ from hwp5.binmodel.tagid61_table import TableBody
26
+
27
+
28
+ class TableControl(CommonControl):
29
+ chid = CHID.TBL
30
+
31
+ def on_child(cls, attributes, context, child):
32
+ child_context, child_model = child
33
+ if child_model['type'] is TableBody:
34
+ # referenced in ListHeader parsing
35
+ context['seen_table_body'] = True
36
+ on_child = classmethod(on_child)
src/hwp5/binmodel/controls/tcps_control.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controlchar import CHID
24
+ from hwp5.dataio import BSTR
25
+ from hwp5.binmodel.controls._shared import Control
26
+
27
+
28
+ class TCPSControl(Control):
29
+ ''' 4.2.10.12. 글자 겹침 '''
30
+ chid = CHID.TCPS
31
+
32
+ def attributes():
33
+ yield BSTR, 'textlength'
34
+ # yield UINT8, 'frameType'
35
+ # yield INT8, 'internalCharacterSize'
36
+ # yield UINT8, 'internalCharacterFold'
37
+ # yield N_ARRAY(UINT8, UINT32), 'characterShapeIds'
38
+ attributes = staticmethod(attributes)
src/hwp5/binmodel/tagid16_document_properties.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_DOCUMENT_PROPERTIES
25
+ from hwp5.dataio import UINT16
26
+ from hwp5.dataio import UINT32
27
+
28
+
29
+ class DocumentProperties(RecordModel):
30
+ ''' 4.1.1. 문서 속성 '''
31
+
32
+ tagid = HWPTAG_DOCUMENT_PROPERTIES
33
+
34
+ def attributes():
35
+ ''' 표 9 문서 속성 '''
36
+ yield UINT16, 'section_count',
37
+ yield UINT16, 'page_startnum',
38
+ yield UINT16, 'footnote_startnum',
39
+ yield UINT16, 'endnote_startnum',
40
+ yield UINT16, 'picture_startnum',
41
+ yield UINT16, 'table_startnum',
42
+ yield UINT16, 'math_startnum',
43
+ yield UINT32, 'list_id',
44
+ yield UINT32, 'paragraph_id',
45
+ yield UINT32, 'character_unit_loc_in_paragraph',
46
+ # yield UINT32, 'flags', # DIFFSPEC
47
+ attributes = staticmethod(attributes)
src/hwp5/binmodel/tagid17_id_mappings.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_ID_MAPPINGS
25
+ from hwp5.dataio import UINT32
26
+
27
+
28
+ class IdMappings(RecordModel):
29
+ ''' 4.1.2. 아이디 매핑 헤더 '''
30
+
31
+ tagid = HWPTAG_ID_MAPPINGS
32
+
33
+ def attributes():
34
+ ''' 표 10 아이디 매핑 헤더 '''
35
+ yield UINT32, 'bindata',
36
+ yield UINT32, 'ko_fonts',
37
+ yield UINT32, 'en_fonts',
38
+ yield UINT32, 'cn_fonts',
39
+ yield UINT32, 'jp_fonts',
40
+ yield UINT32, 'other_fonts',
41
+ yield UINT32, 'symbol_fonts',
42
+ yield UINT32, 'user_fonts',
43
+ yield UINT32, 'borderfills',
44
+ yield UINT32, 'charshapes',
45
+ yield UINT32, 'tabdefs',
46
+ yield UINT32, 'numberings',
47
+ yield UINT32, 'bullets',
48
+ yield UINT32, 'parashapes',
49
+ yield UINT32, 'styles',
50
+
51
+ # memoshapes are found from 5.0.1.7, but not in 5.0.1.6
52
+ yield dict(type=UINT32, name='memoshapes', version=(5, 0, 1, 7))
53
+
54
+ # TODO unknown fields:
55
+ # followings are found from 5.0.3.2, but not in 5.0.3.1
56
+ # but some 5.0.3.3 files do not have them:
57
+ # 5.0.3.3/d6dfac424525298119de54410c3b22d74aa85511
58
+ # yield dict(type=UINT32, name='unknown1', version=(5, 0, 3, 2))
59
+ # yield dict(type=UINT32, name='unknown2', version=(5, 0, 3, 2))
60
+ attributes = staticmethod(attributes)
src/hwp5/binmodel/tagid18_bin_data.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_BIN_DATA
25
+ from hwp5.dataio import Enum
26
+ from hwp5.dataio import Flags
27
+ from hwp5.dataio import UINT16
28
+ from hwp5.dataio import Struct
29
+ from hwp5.dataio import BSTR
30
+ from hwp5.dataio import SelectiveType
31
+ from hwp5.dataio import ref_member_flag
32
+ from hwp5.binmodel._shared import BinStorageId
33
+
34
+
35
+ class BinDataLink(Struct):
36
+ def attributes():
37
+ yield BSTR, 'abspath'
38
+ yield BSTR, 'relpath'
39
+ attributes = staticmethod(attributes)
40
+
41
+
42
+ class BinDataEmbedding(Struct):
43
+ def attributes():
44
+ yield BinStorageId, 'storage_id'
45
+ yield BSTR, 'ext'
46
+ attributes = staticmethod(attributes)
47
+
48
+
49
+ class BinDataStorage(Struct):
50
+ def attributes():
51
+ yield BinStorageId, 'storage_id'
52
+ attributes = staticmethod(attributes)
53
+
54
+
55
+ class BinData(RecordModel):
56
+ ''' 4.1.3. 바이너리 데이터 '''
57
+
58
+ tagid = HWPTAG_BIN_DATA
59
+
60
+ # 표 13 바이너리 데이터 속성
61
+ StorageType = Enum(LINK=0, EMBEDDING=1, STORAGE=2)
62
+ CompressionType = Enum(STORAGE_DEFAULT=0, YES=1, NO=2)
63
+ AccessState = Enum(NEVER=0, OK=1, FAILED=2, FAILED_IGNORED=3)
64
+ Flags = Flags(UINT16,
65
+ 0, 3, StorageType, 'storage',
66
+ 4, 5, CompressionType, 'compression',
67
+ 16, 17, AccessState, 'access')
68
+
69
+ def attributes(cls):
70
+ ''' 표 12 바이너리 데이터 '''
71
+ yield cls.Flags, 'flags'
72
+ yield (SelectiveType(ref_member_flag('flags', 'storage'),
73
+ {cls.StorageType.LINK: BinDataLink,
74
+ cls.StorageType.EMBEDDING: BinDataEmbedding,
75
+ cls.StorageType.STORAGE: BinDataStorage}),
76
+ 'bindata')
77
+ attributes = classmethod(attributes)
src/hwp5/binmodel/tagid19_face_name.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_FACE_NAME
25
+ from hwp5.dataio import Flags
26
+ from hwp5.dataio import Enum
27
+ from hwp5.dataio import BSTR
28
+ from hwp5.dataio import BYTE
29
+ from hwp5.dataio import Struct
30
+
31
+
32
+ class AlternateFont(Struct):
33
+ def attributes():
34
+ yield BYTE, 'kind'
35
+ yield BSTR, 'name'
36
+ attributes = staticmethod(attributes)
37
+
38
+
39
+ class Panose1(Struct):
40
+ ''' 표 17 글꼴 유형 정보 '''
41
+
42
+ FamilyType = Enum('any', 'no_fit', 'text_display', 'script', 'decorative',
43
+ 'pictorial')
44
+
45
+ SerifStyle = Enum('any', 'no_fit', 'cove', 'obtuse_cove', 'square_cove',
46
+ 'obtuse_square_cove', 'square', 'thin', 'bone',
47
+ 'exaggerated', 'triangle', 'normal_sans', 'obtuse_sans',
48
+ 'perp_sans', 'flared', 'rounded')
49
+
50
+ Weight = Enum('any', 'no_fit', 'very_light', 'light', 'thin', 'book',
51
+ 'medium', 'demi', 'bold', 'heavy', 'black', 'nord')
52
+
53
+ Proportion = Enum('any', 'no_fit', 'old_style', 'modern', 'even_width',
54
+ 'expanded', 'condensed', 'very_expanded',
55
+ 'very_condensed', 'monospaced')
56
+
57
+ Contrast = Enum('any', 'no_fit', 'none', 'very_low', 'low', 'medium_low',
58
+ 'medium', 'medium_high', 'high', 'very_high')
59
+
60
+ StrokeVariation = Enum('any', 'no_fit', 'gradual_diag', 'gradual_tran',
61
+ 'gradual_vert', 'gradual_horz', 'rapid_vert',
62
+ 'rapid_horz', 'instant_vert')
63
+
64
+ ArmStyle = Enum('any', 'no_fit', 'straight_horz', 'straight_wedge',
65
+ 'straight_vert', 'straight_single_serif',
66
+ 'straight_double_serif', 'bent_horz', 'bent_wedge',
67
+ 'bent_vert', 'bent_single_serif', 'bent_double_serif')
68
+
69
+ Letterform = Enum('any', 'no_fit', 'normal_contact', 'normal_weighted',
70
+ 'normal_boxed', 'normal_flattened', 'normal_rounded',
71
+ 'normal_off_center', 'normal_square', 'oblique_contact',
72
+ 'oblique_weighted', 'oblique_boxed', 'oblique_flattened',
73
+ 'oblique_rounded', 'oblique_off_center',
74
+ 'oblique_square')
75
+
76
+ Midline = Enum('any', 'no_fit', 'standard_trimmed', 'standard_pointed',
77
+ 'standard_serifed', 'high_trimmed', 'high_pointed',
78
+ 'high_serifed', 'constant_trimmed', 'constant_pointed',
79
+ 'constant_serifed', 'low_trimmed', 'low_pointed',
80
+ 'low_serifed')
81
+
82
+ XHeight = Enum('any', 'no_fit', 'constant_small', 'constant_std',
83
+ 'constant_large', 'ducking_small', 'ducking_std',
84
+ 'ducking_large')
85
+
86
+ def attributes():
87
+ yield BYTE, 'family_type',
88
+ yield BYTE, 'serif_style',
89
+ yield BYTE, 'weight',
90
+ yield BYTE, 'proportion',
91
+ yield BYTE, 'contrast',
92
+ yield BYTE, 'stroke_variation',
93
+ yield BYTE, 'arm_style',
94
+ yield BYTE, 'letterform',
95
+ yield BYTE, 'midline',
96
+ yield BYTE, 'x_height',
97
+ attributes = staticmethod(attributes)
98
+
99
+
100
+ class FaceName(RecordModel):
101
+ ''' 4.1.4. 글꼴 '''
102
+
103
+ tagid = HWPTAG_FACE_NAME
104
+
105
+ # 표 16 대체 글꼴 유형
106
+ FontFileType = Enum(UNKNOWN=0, TTF=1, HFT=2)
107
+
108
+ # 표 15 글꼴 속성
109
+ Flags = Flags(BYTE,
110
+ 0, 1, FontFileType, 'font_file_type',
111
+ 5, 'default',
112
+ 6, 'metric',
113
+ 7, 'alternate')
114
+
115
+ def attributes(cls):
116
+ ''' 표 14 글꼴 '''
117
+ yield cls.Flags, 'flags'
118
+ yield BSTR, 'name'
119
+
120
+ def has_alternate(context, values):
121
+ ''' flags.alternate == 1 '''
122
+ return values['flags'].alternate
123
+
124
+ def has_metric(context, values):
125
+ ''' flags.metric == 1 '''
126
+ return values['flags'].metric
127
+
128
+ def has_default(context, values):
129
+ ''' flags.default == 1 '''
130
+ return values['flags'].default
131
+
132
+ yield dict(type=AlternateFont, name='alternate_font',
133
+ condition=has_alternate)
134
+ yield dict(type=Panose1, name='panose1', condition=has_metric)
135
+ yield dict(type=BSTR, name='default_font', condition=has_default)
136
+ attributes = classmethod(attributes)
src/hwp5/binmodel/tagid20_border_fill.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_BORDER_FILL
25
+ from hwp5.dataio import UINT32
26
+ from hwp5.dataio import UINT16
27
+ from hwp5.dataio import BYTE
28
+ from hwp5.dataio import Flags
29
+ # from hwp5.dataio import N_ARRAY
30
+ from hwp5.binmodel._shared import Border
31
+ from hwp5.binmodel._shared import FillColorPattern
32
+ from hwp5.binmodel._shared import FillGradation
33
+ from hwp5.binmodel._shared import FillImage
34
+
35
+
36
+ class BorderFill(RecordModel):
37
+ ''' 4.1.5. 테두리/배경 '''
38
+
39
+ tagid = HWPTAG_BORDER_FILL
40
+
41
+ # 표 19 테두리/배경 속성
42
+ BorderFlags = Flags(UINT16,
43
+ 0, 'effect_3d',
44
+ 1, 'effect_shadow',
45
+ 2, 4, 'slash',
46
+ 5, 6, 'backslash')
47
+
48
+ # 표 23 채우기 정보
49
+ FillFlags = Flags(UINT32,
50
+ 0, 'colorpattern',
51
+ 1, 'image',
52
+ 2, 'gradation')
53
+
54
+ def attributes(cls):
55
+ ''' 표 18 테두리/배경 속성 '''
56
+ yield cls.BorderFlags, 'borderflags'
57
+ yield Border, 'left',
58
+ yield Border, 'right',
59
+ yield Border, 'top',
60
+ yield Border, 'bottom',
61
+ yield Border, 'diagonal'
62
+ yield cls.FillFlags, 'fillflags'
63
+
64
+ def fill_colorpattern(context, values):
65
+ ''' fillflags.fill_colorpattern '''
66
+ return values['fillflags'].colorpattern
67
+
68
+ def fill_image(context, values):
69
+ ''' fillflags.fill_image '''
70
+ return values['fillflags'].image
71
+
72
+ def fill_gradation(context, values):
73
+ ''' fillflags.fill_gradation '''
74
+ return values['fillflags'].gradation
75
+
76
+ yield dict(type=FillColorPattern, name='fill_colorpattern',
77
+ condition=fill_colorpattern)
78
+ yield dict(type=FillGradation, name='fill_gradation',
79
+ condition=fill_gradation)
80
+ yield dict(type=FillImage, name='fill_image',
81
+ condition=fill_image)
82
+ yield dict(type=UINT32, name='shape',
83
+ condition=fill_gradation)
84
+ yield dict(type=BYTE, name='blur_center',
85
+ condition=fill_gradation)
86
+ # 스펙 1.2의 표28 설명과는 달리,
87
+ # 적어도 5.0.1.7에서, 있는 경우가 있고 없는 경우가 있음
88
+ # yield N_ARRAY(UINT32, BYTE), 'extended' # SPEC
89
+ attributes = classmethod(attributes)
src/hwp5/binmodel/tagid21_char_shape.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_CHAR_SHAPE
25
+ from hwp5.dataio import StructType
26
+ from hwp5.dataio import Struct
27
+ from hwp5.dataio import Enum
28
+ from hwp5.dataio import Flags
29
+ from hwp5.dataio import UINT32
30
+ from hwp5.dataio import INT32
31
+ from hwp5.dataio import INT8
32
+ from hwp5.dataio import UINT8
33
+ from hwp5.dataio import WORD
34
+ from hwp5.binmodel._shared import COLORREF
35
+
36
+
37
+ def LanguageStruct(name, basetype):
38
+ ''' 표 29 글꼴에 대한 언어 '''
39
+ def attributes():
40
+ for lang in ('ko', 'en', 'cn', 'jp', 'other', 'symbol', 'user'):
41
+ yield basetype, lang
42
+ attributes = staticmethod(attributes)
43
+ return StructType(name, (Struct,), dict(basetype=basetype,
44
+ attributes=attributes))
45
+
46
+
47
+ class ShadowSpace(Struct):
48
+ def attributes():
49
+ yield INT8, 'x'
50
+ yield INT8, 'y'
51
+ attributes = staticmethod(attributes)
52
+
53
+
54
+ class CharShape(RecordModel):
55
+ ''' 4.1.6. 글자 모양 '''
56
+
57
+ tagid = HWPTAG_CHAR_SHAPE
58
+
59
+ # 표 30 글자 모양 속성
60
+ Underline = Enum(NONE=0, UNDERLINE=1, LINE_THROUGH=2, OVERLINE=3)
61
+ UnderlineStyle = Enum(SOLID=0, DASHED=1, DOTTED=2, DASH_DOT=3,
62
+ DASH_DOT_DOT=4, LONG_DASHED=5, LARGE_DOTTED=6,
63
+ DOUBLE=7, LOWER_WEIGHTED=8, UPPER_WEIGHTED=9,
64
+ MIDDLE_WEIGHTED=10)
65
+ Flags = Flags(UINT32,
66
+ 0, 'italic',
67
+ 1, 'bold',
68
+ 2, 3, Underline, 'underline',
69
+ 4, 7, UnderlineStyle, 'underline_style',
70
+ 8, 10, 'outline',
71
+ 11, 13, 'shadow')
72
+
73
+ def attributes(cls):
74
+ ''' 표 28 글자 모양 '''
75
+ yield LanguageStruct('FontFace', WORD), 'font_face',
76
+ yield (LanguageStruct('LetterWidthExpansion', UINT8),
77
+ 'letter_width_expansion')
78
+ yield LanguageStruct('LetterSpacing', INT8), 'letter_spacing'
79
+ yield LanguageStruct('RelativeSize', INT8), 'relative_size'
80
+ yield LanguageStruct('Position', INT8), 'position'
81
+ yield INT32, 'basesize',
82
+ yield cls.Flags, 'charshapeflags',
83
+ yield ShadowSpace, 'shadow_space'
84
+ yield COLORREF, 'text_color',
85
+ yield COLORREF, 'underline_color',
86
+ yield COLORREF, 'shade_color',
87
+ yield COLORREF, 'shadow_color',
88
+ # yield UINT16, 'borderfill_id', # DIFFSPEC
89
+ # yield COLORREF, 'strikeoutColor', # DIFFSPEC
90
+ attributes = classmethod(attributes)
src/hwp5/binmodel/tagid22_tab_def.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_TAB_DEF
25
+ from hwp5.dataio import HWPUNIT
26
+ from hwp5.dataio import UINT32
27
+ from hwp5.dataio import Enum
28
+ from hwp5.dataio import Flags
29
+ from hwp5.dataio import Struct
30
+ from hwp5.dataio import N_ARRAY
31
+
32
+
33
+ class Tab(Struct):
34
+
35
+ Kind = Enum(LEFT=0, RIGHT=1, CENTER=2, FLOAT=3)
36
+
37
+ Flags = Flags(UINT32,
38
+ 0, 7, Kind, 'kind',
39
+ 8, 15, 'fill_type')
40
+
41
+ @classmethod
42
+ def attributes(cls):
43
+ yield HWPUNIT, 'pos',
44
+ yield cls.Flags, 'flags'
45
+
46
+
47
+ class TabDef(RecordModel):
48
+ ''' 4.1.7. 탭 정의 '''
49
+
50
+ tagid = HWPTAG_TAB_DEF
51
+
52
+ ''' 표 32 탭 정의 속성 '''
53
+ Flags = Flags(UINT32,
54
+ 0, 'autotab_left',
55
+ 1, 'autotab_right')
56
+
57
+ @classmethod
58
+ def attributes(cls):
59
+ yield dict(type=cls.Flags, name='flags')
60
+ yield dict(type=N_ARRAY(UINT32, Tab), name='tabs')
src/hwp5/binmodel/tagid23_numbering.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_NUMBERING
25
+ from hwp5.dataio import Enum
26
+ from hwp5.dataio import Flags
27
+ from hwp5.dataio import UINT32
28
+ from hwp5.dataio import UINT16
29
+ from hwp5.dataio import INT32
30
+ from hwp5.dataio import BSTR
31
+ from hwp5.dataio import HWPUNIT16
32
+ from hwp5.dataio import Struct
33
+ from hwp5.dataio import ARRAY
34
+
35
+
36
+ class NumberingLevel(Struct):
37
+
38
+ # 표 35 문단 머리 정보 속성
39
+ Align = Enum(LEFT=0, CENTER=1, RIGHT=2, UNKNOWN=3)
40
+ DistanceType = Enum(RATIO=0, VALUE=1)
41
+ Flags = Flags(UINT32,
42
+ 0, 1, Align, 'align',
43
+ 2, 'auto_width',
44
+ 3, 'auto_indent',
45
+ 4, DistanceType, 'space_type')
46
+
47
+ @classmethod
48
+ def attributes(cls):
49
+ ''' 표 34 문단 머리 정보 '''
50
+ yield cls.Flags, 'flags'
51
+ yield HWPUNIT16, 'width_correction'
52
+ yield UINT16, 'space'
53
+ yield INT32, 'charshape_id'
54
+ yield BSTR, 'numbering_format' # see 표 36 문단 번호 형식
55
+
56
+
57
+ class Numbering(RecordModel):
58
+ ''' 4.1.8. 문단 번호 '''
59
+ tagid = HWPTAG_NUMBERING
60
+
61
+ Align = NumberingLevel.Align
62
+ DistanceType = NumberingLevel.DistanceType
63
+ Flags = NumberingLevel.Flags
64
+
65
+ def attributes(cls):
66
+ ''' 표 33 문단 번호 '''
67
+ yield ARRAY(NumberingLevel, 7), 'levels'
68
+ yield UINT16, 'starting_number'
69
+ yield dict(type=ARRAY(UINT32, 7),
70
+ name='unknown',
71
+ version=(5, 0, 3, 0))
72
+ attributes = classmethod(attributes)
src/hwp5/binmodel/tagid24_bullet.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_BULLET
25
+ from hwp5.dataio import INT32
26
+ from hwp5.dataio import UINT32
27
+ from hwp5.dataio import UINT16
28
+ from hwp5.dataio import HWPUNIT16
29
+ from hwp5.dataio import WCHAR
30
+ from hwp5.dataio import Enum
31
+ from hwp5.dataio import Flags
32
+
33
+
34
+ BulletAlignEnum = Enum(LEFT=0, CENTER=1, RIGHT=2)
35
+ BulletFlags = Flags(UINT32,
36
+ 0, 1, BulletAlignEnum, 'align',
37
+ 3, 'auto_indent')
38
+
39
+
40
+ class Bullet(RecordModel):
41
+ ''' 4.1.9. 글머리표 '''
42
+
43
+ tagid = HWPTAG_BULLET
44
+
45
+ @staticmethod
46
+ def attributes():
47
+ # TODO: Spec 1.2 is insufficient and incorrect
48
+ yield BulletFlags, 'flags',
49
+ yield HWPUNIT16, 'width', # 너비, 단위: HWPUNIT
50
+ yield UINT16, 'space', # 본문과의 간격, 단위: %
51
+ yield INT32, 'charshape_id',
52
+ yield WCHAR, 'char'
src/hwp5/binmodel/tagid25_para_shape.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_PARA_SHAPE
25
+ from hwp5.dataio import Enum
26
+ from hwp5.dataio import Flags
27
+ from hwp5.dataio import INT32
28
+ from hwp5.dataio import UINT32
29
+ from hwp5.dataio import UINT16
30
+ from hwp5.dataio import SHWPUNIT
31
+ from hwp5.dataio import HWPUNIT16
32
+
33
+
34
+ class ParaShape(RecordModel):
35
+ ''' 4.1.10. 문단 모양 '''
36
+ tagid = HWPTAG_PARA_SHAPE
37
+
38
+ # 표 39 문단 모양 속성1
39
+ LineSpacingType = Enum(RATIO=0, FIXED=1, SPACEONLY=2, MINIMUM=3)
40
+ Align = Enum(BOTH=0, LEFT=1, RIGHT=2, CENTER=3, DISTRIBUTE=4,
41
+ DISTRIBUTE_SPACE=5)
42
+ VAlign = Enum(FONT=0, TOP=1, CENTER=2, BOTTOM=3)
43
+ LineBreakAlphabet = Enum(WORD=0, HYPHEN=1, CHAR=2)
44
+ LineBreakHangul = Enum(WORD=0, CHAR=1)
45
+ HeadShape = Enum(NONE=0, OUTLINE=1, NUMBER=2, BULLET=3)
46
+ Flags1 = Flags(UINT32,
47
+ 0, 1, LineSpacingType, 'linespacing_type',
48
+ 2, 4, Align, 'align',
49
+ 5, 6, LineBreakAlphabet, 'linebreak_alphabet',
50
+ 7, LineBreakHangul, 'linebreak_hangul',
51
+ 8, 'use_paper_grid',
52
+ 9, 15, 'minimum_space', # 공백 최소값
53
+ 16, 'protect_single_line', # 외톨이줄 보호
54
+ 17, 'with_next_paragraph', # 다음 문단과 함께
55
+ 18, 'protect', # 문단 보호
56
+ 19, 'start_new_page', # 문단 앞에서 항상 쪽 나눔
57
+ 20, 21, VAlign, 'valign',
58
+ 22, 'lineheight_along_fontsize', # 글꼴에 어울리는 줄 높이
59
+ 23, 24, HeadShape, 'head_shape', # 문단 머리 모양
60
+ 25, 27, 'level', # 문단 수준
61
+ 28, 'linked_border', # 문단 테두리 연결 여부
62
+ 29, 'ignore_margin', # 문단 여백 무시
63
+ 30, 'tail_shape') # 문단 꼬리 모양
64
+
65
+ # 표 40 문단 모양 속성2
66
+ Flags2 = Flags(UINT32,
67
+ 0, 1, 'in_single_line',
68
+ 2, 3, 'reserved',
69
+ 4, 'autospace_alphabet',
70
+ 5, 'autospace_number')
71
+
72
+ # 표 41 줄 간격 종류
73
+ Flags3 = Flags(UINT32,
74
+ 0, 4, LineSpacingType, 'linespacing_type3')
75
+
76
+ Flags = Flags1
77
+
78
+ def attributes(cls):
79
+ ''' 표 38 문단 모양 '''
80
+ yield cls.Flags, 'parashapeflags',
81
+ yield INT32, 'doubled_margin_left', # 1/7200 * 2 # DIFFSPEC
82
+ yield INT32, 'doubled_margin_right', # 1/7200 * 2
83
+ yield SHWPUNIT, 'indent',
84
+ yield INT32, 'doubled_margin_top', # 1/7200 * 2
85
+ yield INT32, 'doubled_margin_bottom', # 1/7200 * 2
86
+ yield SHWPUNIT, 'linespacing',
87
+ yield UINT16, 'tabdef_id',
88
+ yield UINT16, 'numbering_bullet_id',
89
+ yield UINT16, 'borderfill_id',
90
+ yield HWPUNIT16, 'border_left',
91
+ yield HWPUNIT16, 'border_right',
92
+ yield HWPUNIT16, 'border_top',
93
+ yield HWPUNIT16, 'border_bottom',
94
+ yield dict(type=cls.Flags2, name='flags2', version=(5, 0, 1, 7))
95
+ # yield cls.Flags3, 'flags3', # DIFFSPEC
96
+ # yield UINT32, 'lineSpacing', # DIFFSPEC
97
+ attributes = classmethod(attributes)
src/hwp5/binmodel/tagid26_style.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_STYLE
25
+ from hwp5.dataio import Enum
26
+ from hwp5.dataio import Flags
27
+ from hwp5.dataio import BYTE
28
+ from hwp5.dataio import BSTR
29
+ from hwp5.dataio import INT16
30
+ from hwp5.dataio import UINT16
31
+
32
+
33
+ class Style(RecordModel):
34
+ ''' 4.1.11. 스타일 '''
35
+ tagid = HWPTAG_STYLE
36
+
37
+ # 표 43 스타일 종류
38
+ Kind = Enum(PARAGRAPH=0, CHAR=1)
39
+ Flags = Flags(BYTE,
40
+ 0, 1, Kind, 'kind')
41
+
42
+ def attributes(cls):
43
+ ''' 표 42 스타일 '''
44
+ yield BSTR, 'local_name',
45
+ yield BSTR, 'name',
46
+ yield cls.Flags, 'flags',
47
+ yield BYTE, 'next_style_id',
48
+ yield INT16, 'lang_id',
49
+ yield UINT16, 'parashape_id',
50
+ yield UINT16, 'charshape_id',
51
+
52
+ # unknown fields
53
+ # following fields are found from 5.0.0.0
54
+ yield UINT16, 'unknown'
55
+ attributes = classmethod(attributes)
src/hwp5/binmodel/tagid27_doc_data.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_DOC_DATA
25
+
26
+
27
+ class DocData(RecordModel):
28
+ ''' 4.1.12. 문서 임의의 데이터 '''
29
+ tagid = HWPTAG_DOC_DATA
30
+
31
+ # TODO
src/hwp5/binmodel/tagid28_distribute_doc_data.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_DISTRIBUTE_DOC_DATA
25
+
26
+
27
+ class DistributeDocData(RecordModel):
28
+ ''' 4.1.13. 배포용 문서 데이터 '''
29
+ tagid = HWPTAG_DISTRIBUTE_DOC_DATA
src/hwp5/binmodel/tagid30_compatible_document.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_COMPATIBLE_DOCUMENT
25
+ from hwp5.dataio import Enum
26
+ from hwp5.dataio import Flags
27
+ from hwp5.dataio import UINT32
28
+
29
+
30
+ class CompatibleDocument(RecordModel):
31
+ ''' 4.1.14. 호환 문서 '''
32
+ tagid = HWPTAG_COMPATIBLE_DOCUMENT
33
+
34
+ # 표 50 대상 프로그램
35
+ Target = Enum(DEFAULT=0, HWP2007=1, MSWORD=2)
36
+ Flags = Flags(UINT32,
37
+ 0, 1, 'target')
38
+
39
+ def attributes(cls):
40
+ ''' 표 49 호환 문서 '''
41
+ yield cls.Flags, 'flags'
42
+ attributes = classmethod(attributes)
src/hwp5/binmodel/tagid31_layout_compatibility.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_LAYOUT_COMPATIBILITY
25
+ from hwp5.dataio import UINT32
26
+
27
+
28
+ class LayoutCompatibility(RecordModel):
29
+ ''' 4.1.15. 레이아웃 호환성 '''
30
+ tagid = HWPTAG_LAYOUT_COMPATIBILITY
31
+
32
+ def attributes():
33
+ ''' 표 51 레이아웃 호환성 '''
34
+ yield UINT32, 'char',
35
+ yield UINT32, 'paragraph',
36
+ yield UINT32, 'section',
37
+ yield UINT32, 'object',
38
+ yield UINT32, 'field',
39
+ attributes = staticmethod(attributes)
src/hwp5/binmodel/tagid32_unknown.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_BEGIN_PLUS_16
25
+
26
+
27
+ class TagModel32(RecordModel):
28
+ tagid = HWPTAG_BEGIN_PLUS_16
29
+ # TODO
src/hwp5/binmodel/tagid50_para_header.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_PARA_HEADER
25
+ from hwp5.dataio import Flags
26
+ from hwp5.dataio import BYTE
27
+ from hwp5.dataio import UINT32
28
+ from hwp5.dataio import UINT16
29
+
30
+
31
+ class Paragraph(RecordModel):
32
+ ''' 4.2.1. 문단 헤더 '''
33
+
34
+ tagid = HWPTAG_PARA_HEADER
35
+
36
+ # 표 54 단 나누기 종류
37
+ SplitFlags = Flags(BYTE,
38
+ 0, 'new_section',
39
+ 1, 'new_columnsdef',
40
+ 2, 'new_page',
41
+ 3, 'new_column')
42
+ ControlMask = Flags(UINT32,
43
+ 2, 'unknown1',
44
+ 11, 'control',
45
+ 21, 'new_number')
46
+ Flags = Flags(UINT32,
47
+ 31, 'unknown',
48
+ 0, 30, 'chars')
49
+
50
+ def attributes(cls):
51
+ ''' 표 53 문단 헤더 '''
52
+ yield cls.Flags, 'text',
53
+ yield cls.ControlMask, 'controlmask',
54
+ yield UINT16, 'parashape_id',
55
+ yield BYTE, 'style_id',
56
+ yield cls.SplitFlags, 'split',
57
+ yield UINT16, 'charshapes',
58
+ yield UINT16, 'rangetags',
59
+ yield UINT16, 'linesegs',
60
+ yield UINT32, 'instance_id',
61
+ attributes = classmethod(attributes)
src/hwp5/binmodel/tagid51_para_text.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+ from __future__ import division
23
+
24
+
25
+
26
+ from hwp5.binmodel._shared import RecordModel
27
+ from hwp5.tagids import HWPTAG_PARA_TEXT
28
+ from hwp5.dataio import ArrayType
29
+ from hwp5.binmodel.controlchar import ControlChar
30
+
31
+
32
+ class ParaTextChunks(list, metaclass=ArrayType):
33
+
34
+ def read(cls, f):
35
+ bytes = f.read()
36
+ return [x for x in cls.parse_chunks(bytes)]
37
+ read = classmethod(read)
38
+
39
+ def parse_chunks(bytes):
40
+ from hwp5.dataio import decode_utf16le_with_hypua
41
+ size = len(bytes)
42
+ idx = 0
43
+ while idx < size:
44
+ ctrlpos, ctrlpos_end = ControlChar.find(bytes, idx)
45
+ if idx < ctrlpos:
46
+ text = decode_utf16le_with_hypua(bytes[idx:ctrlpos])
47
+ yield (idx // 2, ctrlpos // 2), text
48
+ if ctrlpos < ctrlpos_end:
49
+ cch = ControlChar.decode(bytes[ctrlpos:ctrlpos_end])
50
+ yield (ctrlpos // 2, ctrlpos_end // 2), cch
51
+ idx = ctrlpos_end
52
+ parse_chunks = staticmethod(parse_chunks)
53
+
54
+
55
+ class ParaText(RecordModel):
56
+ ''' 4.2.2. 문단의 텍스트 '''
57
+ tagid = HWPTAG_PARA_TEXT
58
+
59
+ def attributes():
60
+ yield ParaTextChunks, 'chunks'
61
+ attributes = staticmethod(attributes)
src/hwp5/binmodel/tagid52_para_char_shape.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+
24
+
25
+ from hwp5.binmodel._shared import RecordModel
26
+ from hwp5.tagids import HWPTAG_PARA_CHAR_SHAPE
27
+ from hwp5.dataio import ArrayType
28
+ from hwp5.dataio import X_ARRAY
29
+ from hwp5.dataio import ARRAY
30
+ from hwp5.dataio import UINT32
31
+ from hwp5.dataio import UINT16
32
+ from hwp5.binmodel._shared import ref_parent_member
33
+
34
+
35
+ class ParaCharShape(RecordModel):
36
+ ''' 4.2.3. 문단의 글자 모양 '''
37
+ tagid = HWPTAG_PARA_CHAR_SHAPE
38
+
39
+ def attributes():
40
+ ''' 표 56 문단의 글자 모양 '''
41
+ yield dict(name='charshapes',
42
+ type=X_ARRAY(ARRAY(UINT32, 2),
43
+ ref_parent_member('charshapes')))
44
+ attributes = staticmethod(attributes)
45
+
46
+
47
+ class ParaCharShapeList(list, metaclass=ArrayType):
48
+
49
+ itemtype = ARRAY(UINT16, 2)
50
+
51
+ def read(cls, f, context):
52
+ bytes = f.read()
53
+ return cls.decode(bytes, context)
54
+ read = classmethod(read)
55
+
56
+ def decode(payload, context=None):
57
+ import struct
58
+ fmt = 'II'
59
+ unitsize = struct.calcsize('<' + fmt)
60
+ unitcount = len(payload) / unitsize
61
+ values = struct.unpack('<' + (fmt * unitcount), payload)
62
+ return list(tuple(values[i * 2:i * 2 + 2])
63
+ for i in range(0, unitcount))
64
+ decode = staticmethod(decode)
src/hwp5/binmodel/tagid53_para_line_seg.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+
24
+
25
+ from hwp5.binmodel._shared import RecordModel
26
+ from hwp5.tagids import HWPTAG_PARA_LINE_SEG
27
+ from hwp5.binmodel._shared import ref_parent_member
28
+ from hwp5.dataio import ArrayType
29
+ from hwp5.dataio import Struct
30
+ from hwp5.dataio import UINT32
31
+ from hwp5.dataio import Flags
32
+ from hwp5.dataio import SHWPUNIT
33
+ from hwp5.dataio import INT32
34
+ from hwp5.dataio import X_ARRAY
35
+
36
+
37
+ class LineSeg(Struct):
38
+ Flags = Flags(UINT32,
39
+ # 0, 'first_in_page',
40
+ # 1, 'first_in_column',
41
+ # 16, 'empty',
42
+ 17, 'line_head',
43
+ 18, 'line_tail',
44
+ # 19, 'auto_hyphen',
45
+ 20, 'indented',
46
+ 21, 'bullet')
47
+
48
+ def attributes(cls):
49
+ yield INT32, 'chpos',
50
+ yield SHWPUNIT, 'y',
51
+ yield SHWPUNIT, 'height',
52
+ yield SHWPUNIT, 'height_text',
53
+ yield SHWPUNIT, 'height_baseline',
54
+ yield SHWPUNIT, 'space_below',
55
+ yield SHWPUNIT, 'x',
56
+ yield SHWPUNIT, 'width'
57
+ yield cls.Flags, 'lineseg_flags'
58
+ attributes = classmethod(attributes)
59
+
60
+
61
+ class ParaLineSeg(RecordModel):
62
+ ''' 4.2.4. 문단의 레이아웃 '''
63
+
64
+ tagid = HWPTAG_PARA_LINE_SEG
65
+
66
+ def attributes(cls):
67
+ ''' 표 57 문단의 레이아웃 '''
68
+ yield dict(name='linesegs',
69
+ type=X_ARRAY(LineSeg, ref_parent_member('linesegs')))
70
+ attributes = classmethod(attributes)
71
+
72
+
73
+ class ParaLineSegList(list, metaclass=ArrayType):
74
+
75
+ itemtype = LineSeg
76
+
77
+ def read(cls, f, context):
78
+ payload = context['stream'].read()
79
+ return cls.decode(context, payload)
80
+ read = classmethod(read)
81
+
82
+ def decode(cls, context, payload):
83
+ import struct
84
+ unitfmt = 'iiiiiiiiHH'
85
+ unitsize = struct.calcsize('<' + unitfmt)
86
+ unitcount = len(payload) // unitsize
87
+ values = struct.unpack('<' + unitfmt * unitcount, payload)
88
+ names = ['chpos', 'y', 'height', 'height2', 'height85', 'space_below',
89
+ 'x', 'width', 'a8', 'flags']
90
+ x = list(dict(zip(names, tuple(values[i * 10:i * 10 + 10])))
91
+ for i in range(0, unitcount))
92
+ for d in x:
93
+ d['flags'] = LineSeg.Flags(d['flags'])
94
+ return x
95
+ decode = classmethod(decode)
src/hwp5/binmodel/tagid54_para_range_tag.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel._shared import RecordModel
24
+ from hwp5.tagids import HWPTAG_PARA_RANGE_TAG
25
+ from hwp5.dataio import UINT32
26
+ from hwp5.dataio import Flags
27
+ from hwp5.dataio import Struct
28
+ from hwp5.dataio import X_ARRAY
29
+ from hwp5.binmodel._shared import ref_parent_member
30
+
31
+
32
+ class RangeTag(Struct):
33
+ ''' 표 58 문단의 영역 태그 '''
34
+
35
+ Tag = Flags(UINT32,
36
+ 0, 23, 'data',
37
+ 24, 31, 'kind')
38
+
39
+ @classmethod
40
+ def attributes(cls):
41
+ yield UINT32, 'start'
42
+ yield UINT32, 'end'
43
+ yield cls.Tag, 'tag'
44
+
45
+
46
+ class ParaRangeTag(RecordModel):
47
+ ''' 4.2.5. 문단의 영역 태그 '''
48
+
49
+ tagid = HWPTAG_PARA_RANGE_TAG
50
+
51
+ @staticmethod
52
+ def attributes():
53
+ yield dict(name='range_tags',
54
+ type=X_ARRAY(RangeTag, ref_parent_member('rangetags')))
src/hwp5/binmodel/tagid55_ctrl_header.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+ from hwp5.binmodel.controls._shared import Control
24
+
25
+ import hwp5.binmodel.controls.bookmark_control
26
+ import hwp5.binmodel.controls.columns_def
27
+ import hwp5.binmodel.controls.common_controls
28
+ import hwp5.binmodel.controls.dutmal
29
+ import hwp5.binmodel.controls.field
30
+ import hwp5.binmodel.controls.gshape_object_control
31
+ import hwp5.binmodel.controls.header_footer
32
+ import hwp5.binmodel.controls.hidden_comment
33
+ import hwp5.binmodel.controls.index_marker
34
+ import hwp5.binmodel.controls.note
35
+ import hwp5.binmodel.controls.numbering
36
+ import hwp5.binmodel.controls.page_hide
37
+ import hwp5.binmodel.controls.page_number_position
38
+ import hwp5.binmodel.controls.page_odd_even
39
+ import hwp5.binmodel.controls.section_def
40
+ import hwp5.binmodel.controls.table_control
41
+ import hwp5.binmodel.controls.tcps_control
42
+
43
+ hwp5
44
+ Control
src/hwp5/binmodel/tagid56_list_header.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # pyhwp : hwp file format parser in python
4
+ # Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ from __future__ import absolute_import
20
+ from __future__ import print_function
21
+ from __future__ import unicode_literals
22
+
23
+
24
+
25
+ from hwp5.binmodel._shared import RecordModelType
26
+ from hwp5.binmodel._shared import RecordModel
27
+ from hwp5.tagids import HWPTAG_LIST_HEADER
28
+ from hwp5.dataio import Enum
29
+ from hwp5.dataio import Flags
30
+ from hwp5.dataio import UINT32
31
+ from hwp5.dataio import UINT16
32
+ from hwp5.dataio import SHWPUNIT
33
+ from hwp5.dataio import HWPUNIT
34
+ from hwp5.dataio import HWPUNIT16
35
+ from hwp5.dataio import BYTE
36
+ from hwp5.binmodel._shared import Margin
37
+ from hwp5.binmodel.controls.table_control import TableControl
38
+ from hwp5.binmodel.controls.gshape_object_control import GShapeObjectControl
39
+ from hwp5.binmodel.controls.header_footer import Header
40
+ from hwp5.binmodel.controls.header_footer import Footer
41
+ from hwp5.binmodel.tagid60_shape_component import ShapeComponent
42
+
43
+
44
+ list_header_models = dict()
45
+
46
+
47
+ class ListHeaderType(RecordModelType):
48
+
49
+ def __new__(mcs, name, bases, attrs):
50
+ cls = RecordModelType.__new__(mcs, name, bases, attrs)
51
+ if 'parent_model_type' in attrs:
52
+ parent_model_type = attrs['parent_model_type']
53
+ before_tablebody = attrs.get('before_tablebody', False)
54
+ list_type_key = parent_model_type, before_tablebody
55
+ assert list_type_key not in list_header_models
56
+ list_header_models[list_type_key] = cls
57
+ return cls
58
+
59
+
60
+ class ListHeader(RecordModel, metaclass=ListHeaderType):
61
+ ''' 4.2.7. 문단 리스트 헤더 '''
62
+
63
+ tagid = HWPTAG_LIST_HEADER
64
+
65
+ VAlign = Enum(TOP=0, MIDDLE=1, BOTTOM=2)
66
+ Flags = Flags(UINT32,
67
+ 0, 2, 'textdirection',
68
+ 3, 4, 'linebreak',
69
+ 5, 6, VAlign, 'valign')
70
+
71
+ def attributes(cls):
72
+ ''' 표 60 문단 리스트 헤더 '''
73
+ yield UINT16, 'paragraphs',
74
+ yield UINT16, 'unknown1',
75
+ yield cls.Flags, 'listflags',
76
+ attributes = classmethod(attributes)
77
+
78
+ extension_types = list_header_models
79
+
80
+ def get_extension_key(context, model):
81
+ ''' (parent model type, after TableBody) '''
82
+ if 'parent' in context:
83
+ context, model = context['parent']
84
+ seen_table_body = context.get('seen_table_body', False)
85
+ return model['type'], seen_table_body
86
+ get_extension_key = staticmethod(get_extension_key)
87
+
88
+
89
+ class TableCaption(ListHeader):
90
+ ''' 표 66 캡션 리스트 '''
91
+ parent_model_type = TableControl
92
+ before_tablebody = False
93
+
94
+ # 표 68 캡션 속성
95
+ Position = Enum(LEFT=0, RIGHT=1, TOP=2, BOTTOM=3)
96
+ Flags = Flags(UINT32,
97
+ 0, 1, Position, 'position',
98
+ # 캡션이 긴 경우 테이블 여백 영역까지 확장
99
+ 2, 'expand_to_margin')
100
+
101
+ def attributes(cls):
102
+ ''' 표 67 캡션 '''
103
+ yield cls.Flags, 'flags',
104
+ yield HWPUNIT, 'width',
105
+ yield HWPUNIT16, 'separation', # 캡션과 틀 사이 간격
106
+ yield HWPUNIT, 'max_width', # expand_to_margin 고려한 최대 너비
107
+ attributes = classmethod(attributes)
108
+
109
+
110
+ class TableCell(ListHeader):
111
+ ''' 표 75 셀 속성 '''
112
+ parent_model_type = TableControl
113
+ before_tablebody = True
114
+
115
+ def attributes():
116
+ yield UINT16, 'col',
117
+ yield UINT16, 'row',
118
+ yield UINT16, 'colspan',
119
+ yield UINT16, 'rowspan',
120
+ yield SHWPUNIT, 'width',
121
+ yield SHWPUNIT, 'height',
122
+ yield Margin, 'padding',
123
+ yield UINT16, 'borderfill_id',
124
+ yield SHWPUNIT, 'unknown_width',
125
+ attributes = staticmethod(attributes)
126
+
127
+
128
+ class GShapeObjectCaption(TableCaption):
129
+ parent_model_type = GShapeObjectControl
130
+
131
+
132
+ class TextboxParagraphList(ListHeader):
133
+ ''' 표 85 그리기 개체 글상자용 텍스트 속성 '''
134
+ parent_model_type = ShapeComponent
135
+
136
+ def attributes():
137
+ yield Margin, 'padding'
138
+ yield HWPUNIT, 'maxwidth'
139
+ attributes = staticmethod(attributes)
140
+
141
+
142
+ class HeaderFooterParagraphList(ListHeader):
143
+ ''' 표 129 머리말/꼬리말 '''
144
+ def attributes():
145
+ yield HWPUNIT, 'width'
146
+ yield HWPUNIT, 'height'
147
+ yield BYTE, 'textrefsbitmap'
148
+ yield BYTE, 'numberrefsbitmap'
149
+ attributes = staticmethod(attributes)
150
+
151
+
152
+ class HeaderParagraphList(HeaderFooterParagraphList):
153
+ parent_model_type = Header
154
+
155
+
156
+ class FooterParagraphList(HeaderFooterParagraphList):
157
+ parent_model_type = Footer