github.com/shakinm/xlsReader@v0.9.12/xls/structure/XLUnicodeRichExtendedString.go (about) 1 package structure 2 3 import ( 4 "github.com/shakinm/xlsReader/helpers" 5 "unicode/utf16" 6 ) 7 8 type XLUnicodeRichExtendedString struct { 9 Cch [2]byte 10 11 /* 12 A - fHighByte (1 bit): A bit that specifies whether the characters in rgb are double-byte characters. 13 MUST be a value from the following table: 14 15 B - reserved1 (1 bit): MUST be zero, and MUST be ignored. 16 C - fExtSt (1 bit): A bit that specifies whether the string contains phonetic string data 17 D - fRichSt (1 bit): A bit that specifies whether the string is a rich string and the string 18 has at least 19 reserved2 (4 bits): MUST be zero, and MUST be ignored. 20 */ 21 FHighByte byte // ABCD 22 CRun [2]byte 23 CbExtRst [4]byte 24 Rgb []byte // If fHighByte is 0x0 size = cch. If fHighByte is 0x1 size = cch*2 25 26 /* 27 An optional array of FormatRun structure that specifies the formatting for each 28 text run. The number of elements in the array is cRun. MUST exist if and only if fRichSt is 0x1. 29 */ 30 RgRun []FormatRun 31 32 /* 33 An optional ExtRst that specifies the phonetic string data. The size of this structure is 34 cbExtRst. MUST exist if and only if fExtSt is 0x1. 35 */ 36 ExtRst ExtRst 37 } 38 39 func (s *XLUnicodeRichExtendedString) Read(stream []byte) uint32 { 40 var rgbSize uint16 41 oft := uint32(0) 42 43 copy(s.Cch[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 44 45 //offset 2 46 s.FHighByte = stream[iOft(&oft, 0):iOft(&oft, 1)][0] 47 48 if s.FHighByte&1 == 1 { 49 rgbSize = helpers.BytesToUint16(s.Cch[:]) * 2 50 51 } else { 52 rgbSize = helpers.BytesToUint16(s.Cch[:]) 53 54 } 55 56 if s.FHighByte>>3&1 == 1 { // if fRichSt == 1 57 58 copy(s.CRun[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 59 } 60 61 if s.FHighByte>>2&1 == 1 { //fExtSt == 1 62 //offset 4 63 copy(s.CbExtRst[:], stream[iOft(&oft, 0):iOft(&oft, 4)]) 64 } 65 66 //offset rgbSize 67 s.Rgb = make([]byte, uint32(rgbSize)) 68 copy(s.Rgb[0:], stream[iOft(&oft, 0):iOft(&oft, uint32(rgbSize))]) 69 70 if s.FHighByte>>3&1 == 1 { // if fRichSt == 1 71 cRunSize := helpers.BytesToUint16(s.CRun[:]) 72 for i := uint16(0); i <= cRunSize-1; i++ { 73 var rgRun FormatRun 74 copy(rgRun.Ich[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 75 copy(rgRun.Ifnt.Ifnt[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 76 s.RgRun = append(s.RgRun, rgRun) 77 } 78 } 79 80 if s.FHighByte>>2&1 == 1 { //fExtSt == 1 81 copy(s.ExtRst.Reserved[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 82 copy(s.ExtRst.Cb[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 83 84 copy(s.ExtRst.Phs.Ifnt.Ifnt[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 85 copy(s.ExtRst.Phs.Info[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 86 87 copy(s.ExtRst.Rphssub.Crun[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 88 copy(s.ExtRst.Rphssub.Cch[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 89 90 copy(s.ExtRst.Rphssub.St.CchCharacters[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 91 92 rgchDataSize := helpers.BytesToUint16(s.ExtRst.Rphssub.St.CchCharacters[:]) * 2 93 for i := uint16(0); i <= rgchDataSize; i++ { 94 s.ExtRst.Rphssub.St.RgchData = append(s.ExtRst.Rphssub.St.RgchData, stream[iOft(&oft, 0):iOft(&oft, 2)]...) 95 } 96 97 //The number of elements in this array is rphssub.crun 98 phRunsSizeL := helpers.BytesToUint16(s.ExtRst.Rphssub.Crun[:]) 99 if phRunsSizeL > 0 { 100 for i := uint16(0); i <= phRunsSizeL; i++ { 101 var phRuns PhRuns 102 copy(phRuns.IchFirst[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 103 copy(phRuns.IchMom[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 104 copy(phRuns.CchMom[:], stream[iOft(&oft, 0):iOft(&oft, 2)]) 105 106 s.ExtRst.Rgphruns = append(s.ExtRst.Rgphruns, phRuns) 107 } 108 } 109 } 110 111 return oft 112 } 113 114 func iOft(offset *uint32, inc uint32) uint32 { 115 *offset = *offset + inc 116 return *offset 117 } 118 119 func (s *XLUnicodeRichExtendedString) String() string { 120 121 if s.FHighByte&1 == 1 { 122 name := helpers.BytesToUints16(s.Rgb[:]) 123 runes := utf16.Decode(name) 124 return string(runes) 125 } else { 126 127 return string(s.Rgb[:]) 128 } 129 130 }