1'''
2Formatting
3==========
4
5The  XF  record is able to store explicit cell formatting attributes or the
6attributes  of  a cell style. Explicit formatting includes the reference to
7a  cell  style  XF  record. This allows to extend a defined cell style with
8some  explicit  attributes.  The  formatting  attributes  are  divided into
96 groups:
10
11=============   ==========================================================
12Group           Attributes
13=============   ==========================================================
14Number format   Number format index (index to FORMAT record)
15Font            Font index (index to FONT record)
16Alignment       Horizontal and vertical alignment, text wrap, indentation,
17                orientation/rotation, text direction
18Border          Border line styles and colours
19Background      Background area style and colours
20Protection      Cell locked, formula hidden
21=============   ==========================================================
22
23For  each  group  a flag in the cell XF record specifies whether to use the
24attributes  contained  in  that  XF  record  or  in  the  referenced  style
25XF  record. In style XF records, these flags specify whether the attributes
26will  overwrite  explicit  cell  formatting  when  the  style is applied to
27a  cell. Changing a cell style (without applying this style to a cell) will
28change  all  cells which already use that style and do not contain explicit
29cell  attributes for the changed style attributes. If a cell XF record does
30not  contain  explicit  attributes  in a group (if the attribute group flag
31is not set), it repeats the attributes of its style XF record.
32
33'''
34
35from . import BIFFRecords
36
37class Font(object):
38
39    ESCAPEMENT_NONE         = 0x00
40    ESCAPEMENT_SUPERSCRIPT  = 0x01
41    ESCAPEMENT_SUBSCRIPT    = 0x02
42
43    UNDERLINE_NONE          = 0x00
44    UNDERLINE_SINGLE        = 0x01
45    UNDERLINE_SINGLE_ACC    = 0x21
46    UNDERLINE_DOUBLE        = 0x02
47    UNDERLINE_DOUBLE_ACC    = 0x22
48
49    FAMILY_NONE         = 0x00
50    FAMILY_ROMAN        = 0x01
51    FAMILY_SWISS        = 0x02
52    FAMILY_MODERN       = 0x03
53    FAMILY_SCRIPT       = 0x04
54    FAMILY_DECORATIVE   = 0x05
55
56    CHARSET_ANSI_LATIN          = 0x00
57    CHARSET_SYS_DEFAULT         = 0x01
58    CHARSET_SYMBOL              = 0x02
59    CHARSET_APPLE_ROMAN         = 0x4D
60    CHARSET_ANSI_JAP_SHIFT_JIS  = 0x80
61    CHARSET_ANSI_KOR_HANGUL     = 0x81
62    CHARSET_ANSI_KOR_JOHAB      = 0x82
63    CHARSET_ANSI_CHINESE_GBK    = 0x86
64    CHARSET_ANSI_CHINESE_BIG5   = 0x88
65    CHARSET_ANSI_GREEK          = 0xA1
66    CHARSET_ANSI_TURKISH        = 0xA2
67    CHARSET_ANSI_VIETNAMESE     = 0xA3
68    CHARSET_ANSI_HEBREW         = 0xB1
69    CHARSET_ANSI_ARABIC         = 0xB2
70    CHARSET_ANSI_BALTIC         = 0xBA
71    CHARSET_ANSI_CYRILLIC       = 0xCC
72    CHARSET_ANSI_THAI           = 0xDE
73    CHARSET_ANSI_LATIN_II       = 0xEE
74    CHARSET_OEM_LATIN_I         = 0xFF
75
76    def __init__(self):
77        # twip = 1/20 of a point = 1/1440 of a inch
78        # usually resolution == 96 pixels per 1 inch
79        # (rarely 120 pixels per 1 inch or another one)
80
81        self.height = 0x00C8 # 200: this is font with height 10 points
82        self.italic = False
83        self.struck_out = False
84        self.outline = False
85        self.shadow = False
86        self.colour_index = 0x7FFF
87        self.bold = False
88        self._weight = 0x0190 # 0x02BC gives bold font
89        self.escapement = self.ESCAPEMENT_NONE
90        self.underline = self.UNDERLINE_NONE
91        self.family = self.FAMILY_NONE
92        self.charset = self.CHARSET_SYS_DEFAULT
93        self.name = 'Arial'
94
95    def get_biff_record(self):
96        height = self.height
97
98        options = 0x00
99        if self.bold:
100            options |= 0x01
101            self._weight = 0x02BC
102        if self.italic:
103            options |= 0x02
104        if self.underline != self.UNDERLINE_NONE:
105            options |= 0x04
106        if self.struck_out:
107            options |= 0x08
108        if self.outline:
109            options |= 0x010
110        if self.shadow:
111            options |= 0x020
112
113        colour_index = self.colour_index
114        weight = self._weight
115        escapement = self.escapement
116        underline = self.underline
117        family = self.family
118        charset = self.charset
119        name = self.name
120
121        return BIFFRecords.FontRecord(height, options, colour_index, weight, escapement,
122                    underline, family, charset,
123                    name)
124
125    def _search_key(self):
126        return (
127            self.height,
128            self.italic,
129            self.struck_out,
130            self.outline,
131            self.shadow,
132            self.colour_index,
133            self.bold,
134            self._weight,
135            self.escapement,
136            self.underline,
137            self.family,
138            self.charset,
139            self.name,
140            )
141
142class Alignment(object):
143    HORZ_GENERAL                = 0x00
144    HORZ_LEFT                   = 0x01
145    HORZ_CENTER                 = 0x02
146    HORZ_RIGHT                  = 0x03
147    HORZ_FILLED                 = 0x04
148    HORZ_JUSTIFIED              = 0x05 # BIFF4-BIFF8X
149    HORZ_CENTER_ACROSS_SEL      = 0x06 # Centred across selection (BIFF4-BIFF8X)
150    HORZ_DISTRIBUTED            = 0x07 # Distributed (BIFF8X)
151
152    VERT_TOP                    = 0x00
153    VERT_CENTER                 = 0x01
154    VERT_BOTTOM                 = 0x02
155    VERT_JUSTIFIED              = 0x03 # Justified (BIFF5-BIFF8X)
156    VERT_DISTRIBUTED            = 0x04 # Distributed (BIFF8X)
157
158    DIRECTION_GENERAL           = 0x00 # BIFF8X
159    DIRECTION_LR                = 0x01
160    DIRECTION_RL                = 0x02
161
162    ORIENTATION_NOT_ROTATED     = 0x00
163    ORIENTATION_STACKED         = 0x01
164    ORIENTATION_90_CC           = 0x02
165    ORIENTATION_90_CW           = 0x03
166
167    ROTATION_0_ANGLE            = 0x00
168    ROTATION_STACKED            = 0xFF
169
170    WRAP_AT_RIGHT               = 0x01
171    NOT_WRAP_AT_RIGHT           = 0x00
172
173    SHRINK_TO_FIT               = 0x01
174    NOT_SHRINK_TO_FIT           = 0x00
175
176    def __init__(self):
177        self.horz = self.HORZ_GENERAL
178        self.vert = self.VERT_BOTTOM
179        self.dire = self.DIRECTION_GENERAL
180        self.orie = self.ORIENTATION_NOT_ROTATED
181        self.rota = self.ROTATION_0_ANGLE
182        self.wrap = self.NOT_WRAP_AT_RIGHT
183        self.shri = self.NOT_SHRINK_TO_FIT
184        self.inde = 0
185        self.merg = 0
186
187    def _search_key(self):
188        return (
189            self.horz, self.vert, self.dire, self.orie, self.rota,
190            self.wrap, self.shri, self.inde, self.merg,
191            )
192
193class Borders(object):
194    NO_LINE = 0x00
195    THIN    = 0x01
196    MEDIUM  = 0x02
197    DASHED  = 0x03
198    DOTTED  = 0x04
199    THICK   = 0x05
200    DOUBLE  = 0x06
201    HAIR    = 0x07
202    #The following for BIFF8
203    MEDIUM_DASHED               = 0x08
204    THIN_DASH_DOTTED            = 0x09
205    MEDIUM_DASH_DOTTED          = 0x0A
206    THIN_DASH_DOT_DOTTED        = 0x0B
207    MEDIUM_DASH_DOT_DOTTED      = 0x0C
208    SLANTED_MEDIUM_DASH_DOTTED  = 0x0D
209
210    NEED_DIAG1      = 0x01
211    NEED_DIAG2      = 0x01
212    NO_NEED_DIAG1   = 0x00
213    NO_NEED_DIAG2   = 0x00
214
215    def __init__(self):
216        self.left   = self.NO_LINE
217        self.right  = self.NO_LINE
218        self.top    = self.NO_LINE
219        self.bottom = self.NO_LINE
220        self.diag   = self.NO_LINE
221
222        self.left_colour   = 0x40
223        self.right_colour  = 0x40
224        self.top_colour    = 0x40
225        self.bottom_colour = 0x40
226        self.diag_colour   = 0x40
227
228        self.need_diag1 = self.NO_NEED_DIAG1
229        self.need_diag2 = self.NO_NEED_DIAG2
230
231    def _search_key(self):
232        return (
233             self.left, self.right, self.top, self.bottom, self.diag,
234             self.left_colour, self.right_colour, self.top_colour,
235             self.bottom_colour, self.diag_colour,
236             self.need_diag1, self.need_diag2,
237            )
238
239class Pattern(object):
240    # patterns 0x00 - 0x12
241    NO_PATTERN      = 0x00
242    SOLID_PATTERN   = 0x01
243
244    def __init__(self):
245        self.pattern = self.NO_PATTERN
246        self.pattern_fore_colour = 0x40
247        self.pattern_back_colour = 0x41
248
249    def _search_key(self):
250        return (
251            self.pattern,
252            self.pattern_fore_colour,
253            self.pattern_back_colour,
254            )
255
256class Protection(object):
257    def __init__(self):
258        self.cell_locked = 1
259        self.formula_hidden = 0
260
261    def _search_key(self):
262        return (
263            self.cell_locked,
264            self.formula_hidden,
265            )
266