Documentation
¶
Overview ¶
Package hwprec reads HWP 5.0 documents (한글 워드프로세서, the .hwp binary format used by every Korean public institution) as a tree of typed records.
It exposes the layer that existing Go HWP tools keep private: the record stream itself (tag, level, size, with the 0xFFF extended-size escape), assembled into a tree by level, plus typed decoders for the records that carry text and table topology — paragraph headers, paragraph text with its control characters, character-shape runs, control headers, tables and cells. Everything else is returned as a raw Record for the caller to decode.
Not implemented: password-encrypted documents and 배포용 (distribution) documents are detected and refused, and DocInfo records are returned raw.
본 제품은 한글과컴퓨터의 한글 문서 파일(.hwp) 공개 문서를 참고하여 개발하였습니다. (This package was developed with reference to Hancom's published HWP document file format specification, as its licence requires us to state.)
Index ¶
Constants ¶
const ( CtrlSectionColumnDef = 2 // extended: 구역 정의 / 단 정의 CtrlFieldStart = 3 // extended CtrlFieldEnd = 4 // inline CtrlTitleMark = 8 // inline CtrlTab = 9 // inline CtrlLineBreak = 10 // char CtrlObject = 11 // extended: 그리기 개체 / 표 CtrlParaBreak = 13 // char CtrlHiddenComment = 15 // extended CtrlFootnote = 17 // extended CtrlAutoNumber = 18 // extended CtrlPageControl = 21 // extended CtrlBookmark = 22 // extended CtrlOverlap = 23 // extended CtrlHyphen = 24 // char CtrlNBSP = 30 // char: 묶음 빈칸 CtrlFixedSpace = 31 // char: 고정폭 빈칸 )
Control codes from 표 6.
const ( TagDocumentProperties = tagBegin + 0 TagIDMappings = tagBegin + 1 TagBinData = tagBegin + 2 TagFaceName = tagBegin + 3 TagBorderFill = tagBegin + 4 TagCharShape = tagBegin + 5 TagTabDef = tagBegin + 6 TagNumbering = tagBegin + 7 TagBullet = tagBegin + 8 TagParaShape = tagBegin + 9 TagStyle = tagBegin + 10 TagDocData = tagBegin + 11 TagDistributeDocData = tagBegin + 12 TagCompatibleDocument = tagBegin + 14 TagLayoutCompatibility = tagBegin + 15 TagTrackChange = tagBegin + 16 TagMemoShape = tagBegin + 76 TagForbiddenChar = tagBegin + 78 TagTrackChangeAuthor = tagBegin + 80 TagParaHeader = tagBegin + 50 TagParaText = tagBegin + 51 TagParaCharShape = tagBegin + 52 TagParaLineSeg = tagBegin + 53 TagParaRangeTag = tagBegin + 54 TagCtrlHeader = tagBegin + 55 TagListHeader = tagBegin + 56 TagPageDef = tagBegin + 57 TagFootnoteShape = tagBegin + 58 TagPageBorderFill = tagBegin + 59 TagShapeComponent = tagBegin + 60 TagTable = tagBegin + 61 TagShapeLine = tagBegin + 62 TagShapeRectangle = tagBegin + 63 TagShapeEllipse = tagBegin + 64 TagShapeArc = tagBegin + 65 TagShapePolygon = tagBegin + 66 TagShapeCurve = tagBegin + 67 TagShapeOLE = tagBegin + 68 TagShapePicture = tagBegin + 69 TagShapeContainer = tagBegin + 70 TagCtrlData = tagBegin + 71 TagEqEdit = tagBegin + 72 TagShapeTextArt = tagBegin + 74 TagFormObject = tagBegin + 75 TagMemoList = tagBegin + 77 TagChartData = tagBegin + 79 TagVideoData = tagBegin + 82 TagShapeUnknown = tagBegin + 99 )
Record tag IDs from the specification (표 57 and 표 7). HWPTAG_BEGIN is 0x10.
Variables ¶
Functions ¶
func CtrlID ¶
CtrlID returns the four-character control id of a CTRL_HEADER payload (spec 표 64), in reading order, e.g. "tbl ", "secd", "cold", "gso ". The file stores it as a little-endian MAKE_4CHID, so bytes are reversed.
Types ¶
type Cell ¶
type Cell struct {
ListHeader
Col, Row uint16
ColSpan, RowSpan uint16
Width, Height uint32 // HWPUNIT (1/7200 inch)
Margins [4]uint16
BorderFillID uint16
Paragraphs []*Paragraph
}
Cell is a table cell: the LIST_HEADER of a table's cell list plus the 26-byte 셀 속성 (spec 표 80).
The cell attributes start at byte 8 of the payload, not at byte 6 as a literal reading of 표 79 (표 65 + 표 80) gives: two bytes the specification does not list sit between them. At offset 6, 406 of the 822 cells in the bundled fixture land outside their tables; at 8, all 822 tile their tables exactly. Producers seen so far: 한글 5.0.5.0.
func DecodeCell ¶
DecodeCell decodes a LIST_HEADER payload that belongs to a table.
type CharShapeRun ¶
CharShapeRun is one entry of HWPTAG_PARA_CHAR_SHAPE (spec 표 61): the character shape (a DocInfo CHAR_SHAPE index) that applies from Pos onward.
func DecodeParaCharShape ¶
func DecodeParaCharShape(b []byte) ([]CharShapeRun, error)
DecodeParaCharShape decodes a PARA_CHAR_SHAPE payload.
type Control ¶
type Control struct {
Code uint16 // 0–31
Pos int // offset in UTF-16 units, the unit PARA_CHAR_SHAPE positions use
Info [6]uint16 // zero for char controls
}
Control is one control character found in paragraph text (spec 표 6). Char controls occupy one UTF-16 unit; inline and extended controls occupy eight: the code, six units of info (inline) or an object pointer (extended), and the code again.
type Document ¶
type Document struct {
Header FileHeader
DocInfo []*Record
Sections [][]*Record
}
Document is a parsed HWP 5.0 file: its header, the DocInfo record tree and one record tree per BodyText section.
func Open ¶
Open parses an HWP 5.0 compound file. For encrypted or distribution documents it returns the header together with ErrEncrypted or ErrDistribution, so callers can still inspect the flags.
type FileHeader ¶
type FileHeader struct {
Version uint32 // 0xMMnnPPrr, e.g. 0x05000500 = 5.0.5.0
Flags uint32 // 속성 bits: 0 compressed, 1 encrypted, 2 distribution, ...
LicenseFlags uint32 // CCL / 공공누리 flags
EncryptVersion uint32
KOGLCountry byte
}
FileHeader is the 256-byte FileHeader stream (spec 표 3).
func ParseFileHeader ¶
func ParseFileHeader(b []byte) (FileHeader, error)
ParseFileHeader decodes the FileHeader stream.
func (FileHeader) Compressed ¶
func (h FileHeader) Compressed() bool
func (FileHeader) DRM ¶
func (h FileHeader) DRM() bool
func (FileHeader) Distribution ¶
func (h FileHeader) Distribution() bool
func (FileHeader) Encrypted ¶
func (h FileHeader) Encrypted() bool
func (FileHeader) HasHistory ¶
func (h FileHeader) HasHistory() bool
func (FileHeader) HasScript ¶
func (h FileHeader) HasScript() bool
func (FileHeader) KOGL ¶
func (h FileHeader) KOGL() bool
func (FileHeader) VersionString ¶
func (h FileHeader) VersionString() string
type ListHeader ¶
ListHeader is the leading part of every HWPTAG_LIST_HEADER (spec 표 65).
func DecodeListHeader ¶
func DecodeListHeader(b []byte) (ListHeader, error)
DecodeListHeader decodes the six bytes every LIST_HEADER starts with.
type ParaHeader ¶
type ParaHeader struct {
NChars uint32 // text length in UTF-16 code units, controls included
ControlMask uint32
ParaShapeID uint16
StyleID uint8
BreakType uint8 // 표 59: 1 section, 2 multi-column, 4 page, 8 column
CharShapeCount uint16
RangeTagCount uint16
LineSegCount uint16
InstanceID uint32
MergedTrack uint16 // 5.0.3.2+, zero when absent
}
ParaHeader is HWPTAG_PARA_HEADER (spec 표 58).
func DecodeParaHeader ¶
func DecodeParaHeader(b []byte) (ParaHeader, error)
DecodeParaHeader decodes a PARA_HEADER payload.
type Paragraph ¶
type Paragraph struct {
Header ParaHeader
Text string
Controls []Control
CharShapes []CharShapeRun
Tables []*Table
Nested []*Paragraph // paragraphs of text boxes, headers/footers, footnotes, comments… anchored here
Record *Record
}
Paragraph is a PARA_HEADER record with its text, character-shape runs and the tables anchored in it, decoded. Record keeps the raw subtree, so controls this package does not model (shapes, footnotes, fields) stay reachable.
func Paragraphs ¶
Paragraphs decodes the paragraphs of a section record tree. Table cells are decoded recursively into Cell.Paragraphs.
type Record ¶
Record is one record of a DocInfo or BodyText stream (spec §4.1): a 32-bit header of TagID(10) | Level(10) | Size(12), then Size bytes of payload. Records whose Level is one deeper than the preceding record are its children; ReadRecords assembles that into Children.
func ReadRecords ¶
ReadRecords parses a decompressed record stream into a tree, using the 10-bit Level field as depth. A Size of 0xFFF means the real size follows the header as a further 32-bit little-endian value (spec 그림 46). Data slices alias b.
type Table ¶
type Table struct {
Attrs uint32 // 표 76
Rows uint16
Cols uint16
CellSpacing uint16 // HWPUNIT16; zero when the payload is too short
Cells []*Cell
}
Table is the fixed part of HWPTAG_TABLE (spec 표 75). Cells are filled in by Paragraphs from the LIST_HEADER records that follow it.
func DecodeTable ¶
DecodeTable decodes the fixed leading fields of a TABLE payload.
type Text ¶
type Text struct {
Text string // characters only; line break → '\n', tab → '\t', 묶음 빈칸 → U+00A0
Controls []Control // every control, in order, with its UTF-16 offset
}
Text is a decoded HWPTAG_PARA_TEXT.
func DecodeParaText ¶
DecodeParaText decodes a PARA_TEXT payload. It fails if an eight-unit control does not end with its own code again, which is how a wrong-width walk shows up (the payload would otherwise desynchronise silently).