Add src
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- src/README.rst +6 -0
- src/hwp5/COPYING +661 -0
- src/hwp5/README +73 -0
- src/hwp5/VERSION.txt +1 -0
- src/hwp5/__init__.py +26 -0
- src/hwp5/binmodel/__init__.py +549 -0
- src/hwp5/binmodel/_shared.py +265 -0
- src/hwp5/binmodel/controlchar.py +215 -0
- src/hwp5/binmodel/controls/__init__.py +94 -0
- src/hwp5/binmodel/controls/_shared.py +59 -0
- src/hwp5/binmodel/controls/bookmark_control.py +50 -0
- src/hwp5/binmodel/controls/columns_def.py +84 -0
- src/hwp5/binmodel/controls/common_controls.py +81 -0
- src/hwp5/binmodel/controls/dutmal.py +48 -0
- src/hwp5/binmodel/controls/field.py +185 -0
- src/hwp5/binmodel/controls/gshape_object_control.py +28 -0
- src/hwp5/binmodel/controls/header_footer.py +48 -0
- src/hwp5/binmodel/controls/hidden_comment.py +34 -0
- src/hwp5/binmodel/controls/index_marker.py +37 -0
- src/hwp5/binmodel/controls/note.py +47 -0
- src/hwp5/binmodel/controls/numbering.py +69 -0
- src/hwp5/binmodel/controls/page_hide.py +42 -0
- src/hwp5/binmodel/controls/page_number_position.py +49 -0
- src/hwp5/binmodel/controls/page_odd_even.py +39 -0
- src/hwp5/binmodel/controls/section_def.py +73 -0
- src/hwp5/binmodel/controls/table_control.py +36 -0
- src/hwp5/binmodel/controls/tcps_control.py +38 -0
- src/hwp5/binmodel/tagid16_document_properties.py +47 -0
- src/hwp5/binmodel/tagid17_id_mappings.py +60 -0
- src/hwp5/binmodel/tagid18_bin_data.py +77 -0
- src/hwp5/binmodel/tagid19_face_name.py +136 -0
- src/hwp5/binmodel/tagid20_border_fill.py +89 -0
- src/hwp5/binmodel/tagid21_char_shape.py +90 -0
- src/hwp5/binmodel/tagid22_tab_def.py +60 -0
- src/hwp5/binmodel/tagid23_numbering.py +72 -0
- src/hwp5/binmodel/tagid24_bullet.py +52 -0
- src/hwp5/binmodel/tagid25_para_shape.py +97 -0
- src/hwp5/binmodel/tagid26_style.py +55 -0
- src/hwp5/binmodel/tagid27_doc_data.py +31 -0
- src/hwp5/binmodel/tagid28_distribute_doc_data.py +29 -0
- src/hwp5/binmodel/tagid30_compatible_document.py +42 -0
- src/hwp5/binmodel/tagid31_layout_compatibility.py +39 -0
- src/hwp5/binmodel/tagid32_unknown.py +29 -0
- src/hwp5/binmodel/tagid50_para_header.py +61 -0
- src/hwp5/binmodel/tagid51_para_text.py +61 -0
- src/hwp5/binmodel/tagid52_para_char_shape.py +64 -0
- src/hwp5/binmodel/tagid53_para_line_seg.py +95 -0
- src/hwp5/binmodel/tagid54_para_range_tag.py +54 -0
- src/hwp5/binmodel/tagid55_ctrl_header.py +44 -0
- 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
|