From 94bd27b1c1119248259a11929910846bb80e164f Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Thu, 20 Oct 2016 21:21:08 +0000 Subject: [PATCH] spready: extended version of the fpspreadsheet demo project fpsctrls - initial upload git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5277 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- applications/spready/fpssylk.pas | 673 +++ applications/spready/readme.txt | 2 + applications/spready/sabout.lfm | 140 + applications/spready/sabout.pas | 130 + applications/spready/scolwidthform.lfm | 109 + applications/spready/scolwidthform.pas | 139 + applications/spready/scsvparamsform.lfm | 554 ++ applications/spready/scsvparamsform.pas | 594 +++ applications/spready/sctrls.pas | 326 ++ applications/spready/scurrencyform.lfm | 172 + applications/spready/scurrencyform.pas | 100 + applications/spready/sformatsettingsform.lfm | 394 ++ applications/spready/sformatsettingsform.pas | 470 ++ applications/spready/shyperlinkform.lfm | 813 +++ applications/spready/shyperlinkform.pas | 550 ++ applications/spready/smain.lfm | 4869 ++++++++++++++++++ applications/spready/smain.pas | 1198 +++++ applications/spready/snumformatform.lfm | 387 ++ applications/spready/snumformatform.pas | 829 +++ applications/spready/spready.ico | Bin 0 -> 132106 bytes applications/spready/spready.lpi | 191 + applications/spready/spready.lpr | 21 + applications/spready/spready.res | Bin 0 -> 101776 bytes applications/spready/srowheightform.lfm | 123 + applications/spready/srowheightform.pas | 143 + applications/spready/ssearchform.lfm | 309 ++ applications/spready/ssearchform.pas | 372 ++ applications/spready/ssortparamsform.lfm | 218 + applications/spready/ssortparamsform.pas | 268 + applications/spready/sutils.pas | 166 + 30 files changed, 14260 insertions(+) create mode 100644 applications/spready/fpssylk.pas create mode 100644 applications/spready/readme.txt create mode 100644 applications/spready/sabout.lfm create mode 100644 applications/spready/sabout.pas create mode 100644 applications/spready/scolwidthform.lfm create mode 100644 applications/spready/scolwidthform.pas create mode 100644 applications/spready/scsvparamsform.lfm create mode 100644 applications/spready/scsvparamsform.pas create mode 100644 applications/spready/sctrls.pas create mode 100644 applications/spready/scurrencyform.lfm create mode 100644 applications/spready/scurrencyform.pas create mode 100644 applications/spready/sformatsettingsform.lfm create mode 100644 applications/spready/sformatsettingsform.pas create mode 100644 applications/spready/shyperlinkform.lfm create mode 100644 applications/spready/shyperlinkform.pas create mode 100644 applications/spready/smain.lfm create mode 100644 applications/spready/smain.pas create mode 100644 applications/spready/snumformatform.lfm create mode 100644 applications/spready/snumformatform.pas create mode 100644 applications/spready/spready.ico create mode 100644 applications/spready/spready.lpi create mode 100644 applications/spready/spready.lpr create mode 100644 applications/spready/spready.res create mode 100644 applications/spready/srowheightform.lfm create mode 100644 applications/spready/srowheightform.pas create mode 100644 applications/spready/ssearchform.lfm create mode 100644 applications/spready/ssearchform.pas create mode 100644 applications/spready/ssortparamsform.lfm create mode 100644 applications/spready/ssortparamsform.pas create mode 100644 applications/spready/sutils.pas diff --git a/applications/spready/fpssylk.pas b/applications/spready/fpssylk.pas new file mode 100644 index 000000000..6ded4c683 --- /dev/null +++ b/applications/spready/fpssylk.pas @@ -0,0 +1,673 @@ +unit fpsSYLK; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + fpstypes, fpspreadsheet, fpsReaderWriter, xlsCommon; + +type + TsSYLKField = record + Name: Char; + Value: String; + end; + TsSYLKFields = array of TsSYLKField; + + + { TsSYLKReader } + + TsSYLKReader = class(TsCustomSpreadReader) + private + FWorksheetName: String; + FPointSeparatorSettings: TFormatSettings; + FDateMode: TDateMode; + protected + function GetFieldValue(const AFields: TsSYLKFields; AFieldName: Char): String; + procedure ProcessCell(const AFields: TsSYLKFields); + procedure ProcessFormat(const AFields: TsSYLKFields); + procedure ProcessLine(const ALine: String); + procedure ProcessRecord(ARecordType: String; const AFields: TsSYLKFields); + public + constructor Create(AWorkbook: TsWorkbook); override; + procedure ReadFromFile(AFileName: String; AParams: TsStreamParams = []); override; + procedure ReadFromStrings(AStrings: TStrings; AParams: TsStreamParams = []); override; + end; + + + { TsSYLKWriter } + TsSYLKWriter = class(TsCustomSpreadWriter) + private + FPointSeparatorSettings: TFormatSettings; + FDateMode: TDateMode; + FSheetIndex: Integer; + function GetFormatStr(ACell: PCell): String; + function GetFormulaStr(ACell: PCell): String; + protected + procedure WriteBool(AStream: TStream; const ARow, ACol: Cardinal; + const AValue: Boolean; ACell: PCell); override; + procedure WriteCellToStream(AStream: TStream; ACell: PCell); override; + procedure WriteComment(AStream: TStream; ACell: PCell); override; + procedure WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal; + const AValue: TDateTime; ACell: PCell); override; + procedure WriteDimensions(AStream: TStream); + procedure WriteEndOfFile(AStream: TStream); + procedure WriteHeader(AStream: TStream); + procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal; + const AValue: string; ACell: PCell); override; + procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; + const AValue: double; ACell: PCell); override; + procedure WriteNumberFormatList(AStream: TStream); + procedure WriteOptions(AStream: TStream); + public + constructor Create(AWorkbook: TsWorkbook); override; + procedure WriteToStream(AStream: TStream; AParams: TsStreamParams = []); override; + end; + + TSYLKSettings = record + SheetIndex: Integer; // W + DateMode: TDateMode; // R/W + end; + +const + STR_FILEFORMAT_SYLK = 'SYLK'; + +var + {@@ Default settings for reading/writing of SYLK files } + SYLKSettings: TSYLKSettings = ( + SheetIndex: 0; + DateMode: dm1900 + ); + + {@@ File format identifier } + sfidSYLK: Integer; + +implementation + +uses + fpsRegFileFormats, fpsUtils, fpsNumFormat; + +{==============================================================================} +{ TsSYLKReader } +{==============================================================================} + +constructor TsSYLKReader.Create(AWorkbook: TsWorkbook); +begin + inherited Create(AWorkbook); + FWorksheetName := 'Sheet1'; // will be replaced by filename + FDateMode := SYLKSettings.DateMode; + FPointSeparatorSettings := DefaultFormatSettings; + FPointSeparatorSettings.DecimalSeparator := '.'; +end; + +function TsSYLKReader.GetFieldValue(const AFields: TsSYLKFields; + AFieldName: Char): String; +var + i: Integer; +begin + for i := 0 to Length(AFields)-1 do + if AFields[i].Name = AFieldName then begin + Result := AFields[i].Value; + exit; + end; + Result := ''; +end; + +procedure TsSYLKReader.ProcessCell(const AFields: TsSYLKFields); +var + row, col: Cardinal; + sval, expr: String; + val: Double; + cell: PCell; +begin + col := StrToInt(GetFieldValue(AFields, 'X')) - 1; + row := StrToInt(GetFieldValue(AFields, 'Y')) - 1; + cell := FWorksheet.GetCell(row, col); + + // Formula + expr := GetFieldValue(AFields, 'E'); // expression in R1C1 syntax + if expr <> '' then + begin + expr := 'A1'; // to do: Convert R1C1 expression to A1 expression! + FWorksheet.WriteFormula(cell, expr); // to do!!!! + exit; + end; + + // Value + sval := GetFieldValue(AFields, 'K'); + if sval <> '' then begin + if sval[1] = '"' then + begin + sval := UnquoteStr(sval); + if (sval = 'TRUE') or (sval = 'FALSE') then + FWorksheet.WriteBoolValue(cell, (sval = 'TRUE')) + else + FWorksheet.WriteText(cell, UnquoteStr(sval)) + // to do: error values + end else begin + val := StrToFloat(sval, FPointSeparatorSettings); + FWorksheet.WriteNumber(cell, val); + // to do: dates + end; + end; +end; + +procedure TsSYLKReader.ProcessFormat(const AFields: TsSYLKFields); +var + cell: PCell; + s, scol, srow, sval, scol1, scol2: String; + col, row, col1, col2: LongInt; + ch1, ch2: Char; + nf: TsNumberFormat; + decs: Integer; + ha: TsHorAlignment; + val: Double; + P: PChar; +begin + nf := nfGeneral; + ha := haDefault; + decs := 0; + + // Format + s := GetFieldValue(AFields, 'F'); + if s <> '' then + begin + ch1 := s[1]; + ch2 := s[Length(s)]; + sval := copy(s, 2, Length(s)); + + // Number format + case ch1 of + 'D': nf := nfGeneral; + 'C': nf := nfCurrency; + 'E': nf := nfExp; + 'F': nf := nfFixed; + 'G': nf := nfGeneral; + '$': ; // no idea what this is + '*': ; // no idea what this is + '%': nf := nfPercentage; + end; + + // Decimal places + TryStrtoInt(sval, decs); + + // Horizontal alignment + case ch2 of + 'D': ha := haDefault; + 'C': ha := haCenter; + 'G': ; // "Standard" ??? + 'L': ha := haLeft; + 'R': ha := haRight; + '-': ; // ??? + 'X': ; // "Fill" + end; + + // Determine whether the format applies to column, row or + + scol := GetFieldValue(AFields, 'C'); + // Column format, not supported yet + if scol <> '' then + exit; + + srow := GetFieldValue(AFields, 'R'); + // Row format, not yet supported + if srow <> '' then + exit; + + // Cell format + scol := GetFieldValue(AFields, 'X'); + srow := GetFieldValue(AFields, 'Y'); + if (scol <> '') and (srow <> '') then + begin + if not TryStrToInt(scol, col) then exit; + if not TryStrToInt(srow, row) then exit; + cell := FWorksheet.GetCell(row, col); + + FWorksheet.WriteNumberFormat(cell, nf, decs); + FWorksheet.WriteHorAlignment(cell, ha); + end; + end; + + // Column width + s := GetFieldValue(AFields, 'W'); + if s <> '' then + begin + scol1 := ''; + P := @s[1]; + while P^ <> ' ' do begin + scol1 := scol1 + P^; + inc(P); + end; + inc(P); + scol2 := ''; + while (P^ <> ' ') do begin + scol2 := scol2 + P^; + inc(P); + end; + inc(P); + sval := ''; + while (P^ <> #0) do begin + sval := sval + P^; + inc(P); + end; + if TryStrToInt(scol1, col1) and + TryStrToInt(scol2, col2) and + TryStrToFloat(sval, val, FPointSeparatorSettings) then + begin + for col := col1-1 to col2-1 do + FWorksheet.WriteColWidth(col, val, suChars); + end; + end; +end; + +procedure TsSYLKReader.ProcessLine(const ALine: String); +var + P: PChar; + i: Integer; + rtd, fval: String; + ftd: Char; + fields: TsSYLKFields; + + procedure StoreField(AName: Char; const AValue: String); + begin + if i >= Length(fields) then SetLength(fields, Length(fields)+100); + fields[i].Name := AName; + fields[i].Value := AValue; + inc(i); + end; + +begin + // Get record type + rtd := ''; + P := @ALine[1]; + while (P^ <> ';') do begin + rtd := rtd + P^; + inc(P); + end; + inc(P); + + if rtd = 'C' then + ftd := 'C'; + + // Get fields + SetLength(fields, 100); + i := 0; + while (P^ <> #0) do begin + ftd := P^; + inc(P); + fval := ''; + while (P^ <> #0) do begin + case P^ of + ';' : begin + inc(P); + if P^ = ';' then begin + fval := fval + P^; + end else + begin + StoreField(ftd, fval); + break; + end; + end; + else fval := fval + P^; + inc(P); + end; + end; + end; + + if fval <> '' then + StoreField(ftd, fval); + + // Process record + SetLength(fields, i); + ProcessRecord(rtd, fields); +end; + +procedure TsSYLKReader.ProcessRecord(ARecordType: String; + const AFields: TsSYLKFields); +begin + case ARecordType of + 'ID': ; // Begin of file - nothing to do for us + 'C' : ProcessCell(AFields); // Content record + 'F' : ProcessFormat(AFields); // Format record + 'E' : ; // End of file + end; +end; + +procedure TsSYLKReader.ReadFromFile(AFileName: String; + AParams: TsStreamParams = []); +begin + FWorksheetName := ChangeFileExt(ExtractFileName(AFileName), ''); + inherited ReadFromFile(AFilename, AParams); +end; + +procedure TsSYLKReader.ReadFromStrings(AStrings: TStrings; + AParams: TsStreamParams = []); +var + i: Integer; +begin + Unused(AParams); + + // Create worksheet + FWorksheet := FWorkbook.AddWorksheet(FWorksheetName, true); + + for i:=0 to AStrings.Count-1 do + ProcessLine(AStrings[i]); +end; + + +{==============================================================================} +{ TsSYLKWriter } +{==============================================================================} + +constructor TsSYLKWriter.Create(AWorkbook: TsWorkbook); +begin + inherited Create(AWorkbook); + FDateMode := SYLKSettings.DateMode; + FSheetIndex := SYLKSettings.SheetIndex; + FPointSeparatorSettings := DefaultFormatSettings; + FPointSeparatorSettings.DecimalSeparator := '.'; +end; + +function TsSYLKWriter.GetFormatStr(ACell: PCell): String; +var + cellFmt: PsCellFormat; + ch1, ch2: Char; + decs: String; + nfp: TsNumFormatParams; + style: String; + fnt: TsFont; +begin + Result := ''; + cellFmt := FWorkbook.GetPointerToCellFormat(ACell^.FormatIndex); + if cellFmt <> nil then + begin + // Number format --> field ";P" + ch1 := 'G'; // general number format + decs := '0'; // decimal places + if (uffNumberFormat in cellFmt^.UsedFormattingFields) then begin + Result := Result + Format(';P%d', [cellFmt^.NumberFormatIndex+1]); // +1 because of General format not in list + nfp := FWorkbook.GetNumberFormat(cellFmt^.NumberFormatIndex); + case nfp.Sections[0].NumFormat of + nfFixed : ch1 := 'F'; + nfCurrency : ch1 := 'C'; + nfPercentage : ch1 := '%'; + nfExp : ch1 := 'E'; + else ch1 := 'G'; + end; + decs := IntToStr(nfp.Sections[0].Decimals); + end else + Result := Result + ';P0'; + + // Horizontal alignment + old-style number format --> field ";F" + ch2 := 'D'; // default alignment + if (uffHorAlign in cellFmt^.UsedFormattingFields) then + case cellFmt^.HorAlignment of + haLeft : ch2 := 'L'; + haCenter: ch2 := 'C'; + haRight : ch2 := 'R'; + end; + Result := Result + ';F' + ch1 + decs + ch2; + + // Font style, Borders, background --> field ";S" + style := ''; + if (uffFont in cellFmt^.UsedFormattingFields) then + begin + fnt := FWorkbook.GetFont(cellFmt^.FontIndex); + if (fssBold in fnt.Style) then style := style + 'D'; + if (fssItalic in fnt.Style) then style := style + 'I'; + end; + if (uffBorder in cellFmt^.UsedFormattingFields) then + begin + if (cbWest in cellFmt^.Border) then style := style + 'L'; + if (cbEast in cellFmt^.Border) then style := style + 'R'; + if (cbNorth in cellFmt^.Border) then style := style + 'T'; + if (cbSouth in cellFmt^.Border) then style := style + 'B'; + end; + if (uffBackground in cellFmt^.UsedFormattingFields) then + style := style + 'S'; + + if style <> '' then + Result := Result + ';S' + style; + end; + + Result := 'F' + Result + Format(';Y%d;X%d', [ACell^.Row+1, ACell^.Col+1]); +end; + +function TsSYLKWriter.GetFormulaStr(ACell: PCell): String; +begin + if HasFormula(ACell) then + Result := ';E' + FWorksheet.ConvertFormulaDialect(ACell, fdExcelR1C1) else + Result := ''; +end; + +{@@ ---------------------------------------------------------------------------- + Writes a boolean value. + In the first line, we write the format code -- see GetFormatStr + In the second line, we write a "C" record containing the fields + - ";X" cell column index (1-based) + - ";Y" cell row index (1-based) + - ";K" boolean value as TRUE or FALSE, no quotes + - ";E" formula in R1C1 syntax, if available -- see GetFormulaStr +-------------------------------------------------------------------------------} +procedure TsSYLKWriter.WriteBool(AStream: TStream; const ARow, ACol: Cardinal; + const AValue: Boolean; ACell: PCell); +const + BOOLSTR: Array[boolean] of String = ('FALSE', 'TRUE'); +var + sval: String; + sfmt: String; +begin + // Format codes + sfmt := GetFormatStr(ACell); + if sfmt <> '' then + sfmt := sfmt + LineEnding; + + // Cell coordinates, value, formula + sval := Format('C;Y$d;X%d;K%s', [ARow+1, ACol+1, BOOLSTR[AValue]]) + GetFormulaStr(ACell); + + // Write out + AppendToStream(AStream, sval + sfmt + LineEnding); +end; + +procedure TsSYLKWriter.WriteCellToStream(AStream: TStream; ACell: PCell); +begin + case ACell^.ContentType of + cctBool: + WriteBool(AStream, ACell^.Row, ACell^.Col, ACell^.BoolValue, ACell); + cctDateTime: + WriteDateTime(AStream, ACell^.Row, ACell^.Col, ACell^.DateTimeValue, ACell); + cctEmpty: + WriteBlank(AStream, ACell^.Row, ACell^.Col, ACell); + cctError: + WriteError(AStream, ACell^.Row, ACell^.Col, ACell^.ErrorValue, ACell); + cctNumber: + WriteNumber(AStream, ACell^.Row, ACell^.Col, ACell^.NumberValue, ACell); + cctUTF8String: + WriteLabel(AStream, ACell^.Row, ACell^.Col, ACell^.UTF8StringValue, ACell); + end; + if FWorksheet.HasComment(ACell) then + WriteComment(AStream, ACell); +end; + +{@@ ---------------------------------------------------------------------------- + Writes a comment record. This is a "C" record containing the fields + - ";X" cell column index (1-based) + - ";Y" cell row index (1-based) + - ";A" comment text, not quoted +-------------------------------------------------------------------------------} +procedure TsSYLKWriter.WriteComment(AStream: TStream; ACell: PCell); +var + comment: String; +begin + comment := FWorksheet.ReadComment(ACell); + if comment <> '' then + AppendToStream(AStream, Format( + 'C;Y%d;X%d;A%s' + LineEnding, [ACell^.Row+1, ACell^.Col+1, comment])); +end; + +{@@ ---------------------------------------------------------------------------- + Writes a date/time value. The date/time cell is just an ordinary number cell, + just formatted with a date/time format. +-------------------------------------------------------------------------------} +procedure TsSYLKWriter.WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal; + const AValue: TDateTime; ACell: PCell); +var + DateSerial: double; +begin + DateSerial := ConvertDateTimeToExcelDateTime(AValue, FDateMode); + WriteNumber(AStream, ARow, ACol, DateSerial, ACell); +end; + +{@@ ---------------------------------------------------------------------------- + Writes out the size of the worksheet (row and column count) + In SYLK, this is a "B" record followed by the fields ";Y" and ";X" containing + the row and column counts. +-------------------------------------------------------------------------------} +procedure TsSYLKWriter.WriteDimensions(AStream: TStream); +begin + AppendToStream(AStream, Format( + 'B;Y%d;X%d;D%d %d %d %d' + LineEnding, [ + FWorksheet.GetLastRowIndex+1, FWorksheet.GetLastColIndex+1, + FWorksheet.GetFirstRowIndex, FWorksheet.GetFirstColIndex, + FWorksheet.GetLastRowIndex, FWorksheet.GetLastColIndex + ])); +end; + +{@@ ---------------------------------------------------------------------------- + Writes out an "E" record which is the last record of a SYLK file +-------------------------------------------------------------------------------} +procedure TsSYLKWriter.WriteEndOfFile(AStream: TStream); +begin + AppendToStream(AStream, + 'E' + LineEnding); +end; + +procedure TsSYLKWriter.WriteHeader(AStream: TStream); +begin + AppendToStream(AStream, + 'ID;PFPS' + LineEnding); // ID + generating app ("FPS" = FPSpreadsheet) +end; + +{@@ ---------------------------------------------------------------------------- + Writes a text value. + In the first line, we write the format code -- see GetFormatStr + In the second line, we write a "C" record containing the fields + - ";X" cell column index (1-based) + - ";Y" cell row index (1-based) + - ";K" text value in double quotes + - ";E" formula in R1C1 syntax, if available -- see GetFormulaStr +-------------------------------------------------------------------------------} +procedure TsSYLKWriter.WriteLabel(AStream: TStream; const ARow, ACol: Cardinal; + const AValue: String; ACell: PCell); +var + sval: String; + sfmt: String; +begin + // Format codes + sfmt := GetFormatStr(ACell); + if sfmt <> '' then + sfmt := sfmt + LineEnding; + + // Cell coordinates, value, formula + sval := Format('C;Y%d;X%d;K"%s"', [ARow+1, ACol+1, AValue]) + GetFormulaStr(ACell); + + // Write out + AppendToStream(AStream, sfmt + sval + LineEnding); +end; + +{@@ ---------------------------------------------------------------------------- + Writes a number value. + In the first line, we write the format code -- see GetFormatStr + In the second line, we write a "C" record containing the fields + - ";X" cell column index (1-based) + - ";Y" cell row index (1-based) + - ";K" number value as unformatted string + - ";E" formula in R1C1 syntax, if available -- see GetFormulaStr +-------------------------------------------------------------------------------} +procedure TsSYLKWriter.WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; + const AValue: double; ACell: PCell); +var + sval: String; + sfmt: String; +begin + // Format codes + sfmt := GetFormatStr(ACell); + if sfmt <> '' then + sfmt := sfmt + LineEnding; + + // Cell coordinates, value, formula + sval := Format('C;Y%d;X%d;K%g', [ARow+1, ACol+1, AValue], FPointSeparatorSettings); + sval := sval + GetFormulaStr(ACell); + + // Write out + AppendToStream(AStream, sfmt + sval + LineEnding); +end; + +{@@ ---------------------------------------------------------------------------- + Writes the list of number formats. + In SYLK, this is a sequence of "P" records. Each record contains the Excel + format string with field identifier ";P" +-------------------------------------------------------------------------------} +procedure TsSYLKWriter.WriteNumberFormatList(AStream: TStream); +var + nfp: TsNumFormatParams; + nfs: String; + i, j: Integer; +begin + AppendToStream(AStream, + 'P;PGeneral' + LineEnding); + + for i:=0 to FWorkbook.GetNumberFormatCount-1 do begin + nfp := FWorkbook.GetNumberFormat(i); + nfs := BuildFormatStringFromSection(nfp.Sections[0]); + for j:=1 to High(nfp.Sections) do + nfs := nfs + ';;' + BuildFormatStringFromSection(nfp.Sections[j]); + AppendToStream(AStream, + 'P;P' + nfs + LineEnding); + end; +end; + +procedure TsSYLKWriter.WriteOptions(AStream: TStream); +var + dateModeStr: String; + A1ModeStr: String; +begin + A1ModeStr := ';L'; // Display formulas in A1 mode. + + case FDateMode of // Datemode 1900 or 1904 + dm1900: dateModeStr := ';V0'; + dm1904: dateModeStr := ';V4'; + end; + + AppendToStream(AStream, + 'O' + A1ModeStr + dateModeStr + LineEnding + ); +end; + +procedure TsSYLKWriter.WriteToStream(AStream: TStream; + AParams: TsStreamParams = []); +begin + Unused(AParams); + if (FSheetIndex < 0) or (FSheetIndex >= FWorkbook.GetWorksheetCount) then + raise Exception.Create('[TsSYLKWriter.WriteToStream] Non-existing worksheet.'); + + FWorksheet := FWorkbook.GetWorksheetByIndex(FSheetIndex); + + WriteHeader(AStream); + WriteNumberFormatList(AStream); + WriteDimensions(AStream); + WriteOptions(AStream); + WriteCellsToStream(AStream, FWorksheet.Cells); + WriteEndOfFile(AStream); +end; + +initialization + + sfidSYLK := RegisterSpreadFormat(sfUser, + TsSYLKReader, TsSYLKWriter, + STR_FILEFORMAT_SYLK, 'SYLK', ['.slk', '.sylk'] + ); + +end. + diff --git a/applications/spready/readme.txt b/applications/spready/readme.txt new file mode 100644 index 000000000..c58bfe6d5 --- /dev/null +++ b/applications/spready/readme.txt @@ -0,0 +1,2 @@ +spready is a relatively complex demonstration of the fpspreadsheet library +and its visual controls. diff --git a/applications/spready/sabout.lfm b/applications/spready/sabout.lfm new file mode 100644 index 000000000..eeb6fabee --- /dev/null +++ b/applications/spready/sabout.lfm @@ -0,0 +1,140 @@ +object AboutForm: TAboutForm + Left = 338 + Height = 294 + Top = 153 + Width = 375 + BorderStyle = bsSizeToolWin + Caption = 'About Spready' + ClientHeight = 294 + ClientWidth = 375 + Color = clWindow + Constraints.MinHeight = 275 + Constraints.MinWidth = 330 + OnCreate = FormCreate + Position = poMainFormCenter + LCLVersion = '1.7' + object Panel1: TPanel + Left = 0 + Height = 90 + Top = 0 + Width = 375 + Align = alTop + BevelOuter = bvNone + ClientHeight = 90 + ClientWidth = 375 + Color = clWindow + ParentColor = False + TabOrder = 0 + object IconImage: TImage + Left = 8 + Height = 64 + Top = 16 + Width = 64 + end + object BtnClose: TButton + AnchorSideTop.Control = Panel1 + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = Panel1 + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = IconImage + AnchorSideBottom.Side = asrBottom + Left = 292 + Height = 29 + Top = 51 + Width = 75 + Anchors = [akRight, akBottom] + BorderSpacing.Right = 8 + Cancel = True + Caption = 'Close' + Default = True + ModalResult = 1 + TabOrder = 0 + end + object LblVersion: TLabel + AnchorSideLeft.Control = IconImage + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Side = asrBottom + AnchorSideBottom.Control = IconImage + AnchorSideBottom.Side = asrBottom + Left = 84 + Height = 15 + Top = 65 + Width = 54 + Anchors = [akLeft, akBottom] + BorderSpacing.Left = 12 + Caption = 'LblVersion' + Font.Color = clNavy + ParentColor = False + ParentFont = False + end + object Image1: TImage + AnchorSideLeft.Control = IconImage + AnchorSideLeft.Side = asrBottom + AnchorSideBottom.Control = LblVersion + Left = 84 + Height = 44 + Top = 21 + Width = 156 + Anchors = [akLeft, akBottom] + AutoSize = True + BorderSpacing.Left = 12 + Picture.Data = { + 1754506F727461626C654E6574776F726B47726170686963B805000089504E47 + 0D0A1A0A0000000D494844520000009C0000002C08060000009072D138000000 + 097048597300000EC300000EC301C76FA8640000056A4944415478DAED5CDB6D + 5B310CF5000182204FE7A30B74824EE00D324137F002052E50B46EF2D311BA42 + 47E80CDDA15BB8396804B034251D52F73A06C20F02ADE32B51D4111F47BC5EED + F7FB554ACAB1248DF016377DF5695FE4E6E6DBF6A4007777F7B879566ABABCDC + FD948A42CECFBFFCC6E7507ABD7E7A9F9B99800B030E4003A034C85A929B9980 + 0B01EEFA7AF7DD03B4045C022E0C3828A08104003E7BBC87F5FAF183147CF7E2 + E2EBAF045C022E04B8FBFBA77752198089C9CDF0DCD5D5EE476E6602CE053819 + 4ACFCE3EFF0190728312708B014E1609005F6E4E026E51C0BDA6222909B8045C + 02EE78211505C3B116890A184507F246492A23ACA31A1E9D03B928C6F2AEEFF6 + F6F12388ED51BDA41E18136BD51C671917FC67C4BE18DB22E8B14E6DEFD65E48 + D601EB8EE82275D0766EF26F00C292804305CC90CB6C056CCD813548C030BC21 + 40517B460A0CCB82C1C36DB2E30A2A6BEA8D89F594FDEC1DFE110C68A6433FDF + FC3204C65F0270001BB3A91E8FA4E780B7F012D55ED29BF10211129D8D30D223 + 3102CFDC0BA9725FBC7497E4712DDB50C42F4E5C248434C0309545C1605618B1 + 3C536FF1B539A0BF9C0360B7C6D29EC2D2CDF2563D8F6490E807EB857D35787A + F995D603D1C2F248F8AC44121D51AC39F4B89E7DEE311DAEAB2D7C1EE5E66AE3 + 794F700BF8DAF81E7A479FFCDE73F0FC6CE829A0646C2737ACE53DB5F7663CA2 + E50D2DC0E14046A29CB6A17569D0BABCAFE63E11E045F314BDF81610A261295A + 30C9E4B8E57D3D9CA6CEA16A373D525FFC9B1D5FEF69CD8B46EC211D55ED19D7 + 203A77F194D4FA790F60F50D083B079B061C9E4CEE390D8E39725D23E9DEF40E + A127B1D79EB9B687FA7BCC7E4930D7745AB15EC6EA87F3A03FEA79ACF0513BF5 + 3AA446AA3C8F6E1A1CA3792ECB93497DBDD485D6B9E534744ECC1EBEA653F028 + 0B835AC0C304BD4B7E8FF291536F25E711DEC8AB5BD4D3604DB0273C09361D21 + D9B2AD0508F93D2F85E2217E6564E91D60991F36D39EC809C486EB5CA0A7D028 + BBCD3C1F9D23425B58D29BB310C9A3634ADB2F654BB608B03D7DDDF90CB97EA3 + 8C9F12707122B978ACDE98C7B0A5A7A1C393920CE71B1A7409B8FE2D40B9C62A + E4B4CEFD4E0970B278A8E5661294BDB46218708709BD9D388F18894DCEE700DC + 9C97D93A24FD6B68ED1716A70438234FDDD4F69FBA753956F7C188912255AA67 + 0EE9A5BD45034BE778AA664F0EE7ED5BF454A9D63A34DF28FFC6E8F22A80F31A + 89A501A280831197E89251C9FD1421BA7B55AA07C81677C8D8491FF89ACD99D7 + 1166081BFF1B8809775EEE88BD4C8E022E42722E15AAF55D76252FDC46F93FA6 + 2861F334095E969E095FC1D492E2DA66792984887147C2F6487BD05CDC236CC7 + 5C3DE943CEEA6B75CF44F6A1CC27531196833C3050ADE380F10CACF76195D4EE + DFD395E1059CBEC2630F5FEB8D35DDCCD8F39CECE5BAE5A97AFAD6DAC1583B59 + 5C5B246235C31E0C0950F5DE47650C6A75721443E9D88FFF6B00046E33DCD59B + D5855B3B14F0165247E640CA2648ED3D0A18643ED95A87F672561B96E804DECA + F1E6C875A3B733B3F0511130781A1D5F366AB334BDE16D0A65F8474F83642958 + D875E808C0761247ED546B68F5E4BCD593C60A50CF4C682D92011DBC0CFB4339 + 73F069588BE7FA89494118D0C974C1B30EEB9AB1424A4F73D84947016FBE5B25 + 2CA10806D313C07825D4BA905D5924E602F0F48B2A98C3DB4F3F27815BF4B252 + 87975F8C9A3C2FBC582F0A95B4458F135987754F0BDDAD9465C44E3A24BBF7E8 + 2DBC9A96329FF4DE5948C0A5CC2A11323B019712BD377F1825C8137029A18221 + 4A8E27E052429D2FD197E413702947F36E09B8148AEC3D7C3738FE03E209B814 + 5707F4E8EFCD24E05268C0CDF1E34609B894EE5BFD233FF1F16A804B4981FC05 + 9DCF04A745BF70B30000000049454E44AE426082 + } + end + end + object Bevel1: TBevel + Left = 0 + Height = 6 + Top = 90 + Width = 375 + Align = alTop + Shape = bsTopLine + end +end diff --git a/applications/spready/sabout.pas b/applications/spready/sabout.pas new file mode 100644 index 000000000..310235630 --- /dev/null +++ b/applications/spready/sabout.pas @@ -0,0 +1,130 @@ +unit sAbout; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, IpHtml, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, + ExtCtrls, StdCtrls; + +type + + { TAboutForm } + + TAboutForm = class(TForm) + Bevel1: TBevel; + BtnClose: TButton; + IconImage: TImage; + Image1: TImage; + LblVersion: TLabel; + Panel1: TPanel; + procedure FormCreate(Sender: TObject); + procedure HTMLViewerHotClick(Sender: TObject); + private + { private declarations } + FHTMLViewer: TIpHtmlPanel; + public + { public declarations } + end; + +var + AboutForm: TAboutForm; + +implementation + +{$R *.lfm} + +uses + LCLIntf, Types, resource, versiontypes, versionresource; + +const + LE = LineEnding; + + HTMLStr = + ' '+ LE + + ''+LE+ + '' + LE + + ' ' + LE + + ' ' + LE + + '' + LE + + '

Compiler and libaries:

' + LE + + ' ' + LE + + '

Icons:

' + LE + + ' ' + LE + + '' + LE + + ''; + + +function ResourceVersionInfo: String; +var + Stream: TResourceStream; + vr: TVersionResource; + fi: TVersionFixedInfo; +begin + Result := ''; + try + { This raises an exception if version info has not been incorporated into the + binary (Lazarus Project -> Project Options -> Version Info -> Version numbering). } + Stream:= TResourceStream.CreateFromID(HINSTANCE, 1, PChar(RT_VERSION)); + try + vr := TVersionResource.Create; + try + vr.SetCustomRawDataStream(Stream); + fi := vr.FixedInfo; + Result := Format('%d.%d', [ + fi.FileVersion[0], fi.FileVersion[1] + ]); + vr.SetCustomRawDataStream(nil) + finally + vr.Free + end; + finally + Stream.Free + end; + except + end; +end; + +procedure TAboutForm.FormCreate(Sender: TObject); +var + sz: TSize; +begin + sz.cx := 64; //128; + sz.cy := 64; //128; + + IconImage.Picture.Icon := Application.Icon; + IconImage.Picture.Icon.Current := Application.Icon.GetBestIndexForSize(sz); //4; + LblVersion.Caption := 'Version ' + ResourceVersionInfo; + + FHTMLViewer := TIpHtmlPanel.Create(self); + FHTMLViewer.Parent := self; + FHTMLViewer.Align := alClient; + FHTMLViewer.DefaultFontSize := 9; + FHTMLViewer.OnHotClick := @HTMLViewerHotClick; + FHTMLViewer.SetHtmlFromStr(HTMLStr); +end; + +procedure TAboutForm.HTMLViewerHotClick(Sender: TObject); +begin + OpenURL((Sender as TIpHtmlPanel).HotURL); +end; + + +end. + diff --git a/applications/spready/scolwidthform.lfm b/applications/spready/scolwidthform.lfm new file mode 100644 index 000000000..d41ddf893 --- /dev/null +++ b/applications/spready/scolwidthform.lfm @@ -0,0 +1,109 @@ +object ColWidthForm: TColWidthForm + Left = 479 + Height = 178 + Top = 289 + Width = 349 + HorzScrollBar.Page = 320 + HorzScrollBar.Range = 320 + VertScrollBar.Page = 141 + VertScrollBar.Range = 141 + BorderStyle = bsDialog + Caption = 'ColWidthForm' + ClientHeight = 178 + ClientWidth = 349 + OnCreate = FormCreate + Position = poMainFormCenter + LCLVersion = '1.7' + object ButtonPanel1: TButtonPanel + Left = 6 + Height = 34 + Top = 138 + Width = 337 + OKButton.Name = 'OKButton' + OKButton.DefaultCaption = True + HelpButton.Name = 'HelpButton' + HelpButton.DefaultCaption = True + CloseButton.Name = 'CloseButton' + CloseButton.Caption = 'Close' + CloseButton.DefaultCaption = False + CancelButton.Name = 'CancelButton' + CancelButton.DefaultCaption = True + TabOrder = 0 + ShowButtons = [pbOK, pbCancel] + end + object EdColWidth: TFloatSpinEdit + AnchorSideLeft.Control = LblColWidth + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = RbCustom + AnchorSideTop.Side = asrBottom + Left = 124 + Height = 23 + Top = 94 + Width = 74 + Alignment = taRightJustify + BorderSpacing.Left = 24 + BorderSpacing.Top = 24 + BorderSpacing.Bottom = 24 + Increment = 1 + MaxValue = 100 + MinValue = 0 + TabOrder = 1 + Value = 15 + end + object LblColWidth: TLabel + AnchorSideTop.Control = EdColWidth + AnchorSideTop.Side = asrCenter + Left = 24 + Height = 15 + Top = 98 + Width = 76 + BorderSpacing.Left = 24 + BorderSpacing.Bottom = 24 + Caption = 'Column width' + ParentColor = False + end + object CbUnits: TComboBox + AnchorSideLeft.Control = EdColWidth + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = EdColWidth + AnchorSideTop.Side = asrCenter + Left = 206 + Height = 23 + Top = 94 + Width = 114 + BorderSpacing.Left = 8 + ItemHeight = 15 + OnChange = CbUnitsChange + Style = csDropDownList + TabOrder = 2 + end + object RbDefault: TRadioButton + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = Owner + Left = 24 + Height = 19 + Top = 24 + Width = 58 + BorderSpacing.Left = 24 + BorderSpacing.Top = 24 + Caption = 'Default' + OnChange = ColWidthTypeChanged + TabOrder = 3 + end + object RbCustom: TRadioButton + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = RbDefault + AnchorSideTop.Side = asrBottom + Left = 24 + Height = 19 + Top = 51 + Width = 62 + BorderSpacing.Left = 24 + BorderSpacing.Top = 8 + Caption = 'Custom' + Checked = True + OnChange = ColWidthTypeChanged + TabOrder = 4 + TabStop = True + end +end diff --git a/applications/spready/scolwidthform.pas b/applications/spready/scolwidthform.pas new file mode 100644 index 000000000..e764093c3 --- /dev/null +++ b/applications/spready/scolwidthform.pas @@ -0,0 +1,139 @@ +unit sColWidthForm; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ButtonPanel, + StdCtrls, Spin, ExtCtrls, fpsTypes, fpspreadsheet; + +type + + { TColWidthForm } + + TColWidthForm = class(TForm) + ButtonPanel1: TButtonPanel; + CbUnits: TComboBox; + EdColWidth: TFloatSpinEdit; + LblColWidth: TLabel; + RbDefault: TRadioButton; + RbCustom: TRadioButton; + procedure CbUnitsChange(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure ColWidthTypeChanged(Sender: TObject); + private + FWorkbook: TsWorkbook; + FOldUnits: TsSizeUnits; + function GetColWidth: Single; + function GetColWidthType: TsColWidthType; + function GetUnits: TsSizeUnits; + procedure SetColWidth(AValue: Single); + procedure SetColWidthType(AValue: TsColWidthType); + procedure SetUnits(AValue: TsSizeUnits); + procedure SetWorkbook(AValue: TsWorkbook); + protected + + public + procedure SetData(AWorkbook: TsWorkbook; AColWidth: single; + AColWidthType: TsColWidthType); + property ColWidth: Single read GetColWidth; + property ColWidthType: TsColWidthType read GetColWidthType; + property Units: TsSizeUnits read GetUnits; + end; + +var + ColWidthForm: TColWidthForm; + +implementation + +{$R *.lfm} + +{ TColWidthForm } + +procedure TColWidthForm.CbUnitsChange(Sender: TObject); +begin + if FWorkbook <> nil then + EdColWidth.Value := FWorkbook.ConvertUnits(EdColWidth.Value, FOldUnits, GetUnits); + FOldUnits := GetUnits; +end; + +procedure TColWidthForm.FormCreate(Sender: TObject); +begin + CbUnits.Items.Clear; + CbUnits.Items.AddObject('Characters', TObject(PtrInt(ord(suChars)))); + CbUnits.Items.AddObject('mm', TObject(PtrInt(ord(suMillimeters)))); + CbUnits.Items.AddObject('cm', TObject(PtrInt(ord(suCentimeters)))); + CbUnits.Items.AddObject('Points', TObject(PtrInt(ord(suPoints)))); + CbUnits.Items.AddObject('Inches', TObject(PtrInt(ord(suInches)))); +end; + +function TColWidthForm.GetColWidth: Single; +begin + Result := EdColWidth.Value; +end; + +function TColWidthForm.GetColWidthType: TsColWidthType; +begin + if RbDefault.Checked then + Result := cwtDefault + else + Result := cwtCustom; +end; + +function TColWidthForm.GetUnits: TsSizeUnits; +begin + if CbUnits.ItemIndex = -1 then + Result := FWorkbook.Units else + Result := TsSizeUnits(IntPtr(CbUnits.Items.Objects[CbUnits.ItemIndex])); +end; + +procedure TColWidthForm.ColWidthTypeChanged(Sender: TObject); +begin + LblColWidth.Enabled := RbCustom.Checked; + EdColWidth.Enabled := RbCustom.Checked; + CbUnits.Enabled := RbCustom.Checked; +end; + +procedure TColWidthForm.SetData(AWorkbook: TsWorkbook; AColWidth: Single; + AColWidthType: TsColWidthType); +begin + SetWorkbook(AWorkbook); + SetColWidth(AColWidth); + SetUnits(AWorkbook.Units); + SetColWidthType(AColWidthType); +end; + +procedure TColWidthForm.SetColWidth(AValue: Single); +begin + EdColWidth.Value := AValue; +end; + +procedure TColWidthForm.SetColWidthType(AValue: TsColWidthType); +begin + RbDefault.Checked := AValue = cwtDefault; + RbCustom.Checked := AValue = cwtCustom; + ColWidthTypeChanged(nil); +end; + +procedure TColWidthForm.SetUnits(AValue: TsSizeUnits); +var + i: Integer; +begin + FOldUnits := GetUnits; + for i:=0 to CbUnits.Items.Count-1 do + if TsSizeUnits(IntPtr(CbUnits.Items.Objects[i])) = AValue then + begin + CbUnits.ItemIndex := i; + exit; + end; +end; + +procedure TColWidthForm.SetWorkbook(AValue: TsWorkbook); +begin + FWorkbook := AValue; + FOldUnits := FWorkbook.Units; +end; + +end. + diff --git a/applications/spready/scsvparamsform.lfm b/applications/spready/scsvparamsform.lfm new file mode 100644 index 000000000..78a484a1c --- /dev/null +++ b/applications/spready/scsvparamsform.lfm @@ -0,0 +1,554 @@ +object CSVParamsForm: TCSVParamsForm + Left = 638 + Height = 555 + Top = 250 + Width = 470 + BorderStyle = bsDialog + Caption = 'Parameters for comma-delimited files' + ClientHeight = 555 + ClientWidth = 470 + OnCloseQuery = FormCloseQuery + OnCreate = FormCreate + Position = poMainFormCenter + LCLVersion = '1.5' + object ButtonPanel: TButtonPanel + Left = 6 + Height = 34 + Top = 515 + Width = 458 + OKButton.Name = 'OKButton' + OKButton.DefaultCaption = True + HelpButton.Name = 'HelpButton' + HelpButton.DefaultCaption = True + CloseButton.Name = 'CloseButton' + CloseButton.DefaultCaption = True + CancelButton.Name = 'CancelButton' + CancelButton.DefaultCaption = True + TabOrder = 0 + ShowButtons = [pbOK, pbCancel] + end + object PageControl: TPageControl + Left = 8 + Height = 499 + Top = 8 + Width = 454 + ActivePage = PgGeneralParams + Align = alClient + BorderSpacing.Around = 8 + MultiLine = True + TabIndex = 0 + TabOrder = 1 + Options = [nboMultiLine] + object PgGeneralParams: TTabSheet + Caption = 'General' + ClientHeight = 471 + ClientWidth = 446 + object LblQuoteChar: TLabel + Left = 16 + Height = 15 + Top = 84 + Width = 88 + Caption = 'Quote character:' + FocusControl = CbQuoteChar + ParentColor = False + end + object CbQuoteChar: TComboBox + Left = 156 + Height = 23 + Top = 80 + Width = 275 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'none' + 'double ( " )' + 'single ( '' )' + ) + Style = csDropDownList + TabOrder = 2 + Text = 'none' + end + object CbDelimiter: TComboBox + Left = 156 + Height = 23 + Top = 16 + Width = 275 + ItemHeight = 15 + ItemIndex = 4 + Items.Strings = ( + 'Comma ( , )' + 'Semicolon ( ; )' + 'Colon ( : )' + 'Bar ( | )' + 'TAB' + ) + Style = csDropDownList + TabOrder = 0 + Text = 'TAB' + end + object Label3: TLabel + Left = 16 + Height = 15 + Top = 19 + Width = 96 + Caption = 'Column delimiter:' + FocusControl = CbDelimiter + ParentColor = False + end + object Label4: TLabel + Left = 16 + Height = 15 + Top = 51 + Width = 65 + Caption = 'Line ending:' + FocusControl = CbLineEnding + ParentColor = False + end + object CbLineEnding: TComboBox + Left = 156 + Height = 23 + Top = 48 + Width = 275 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'System' + 'CR+LF (Windows)' + 'CR (Mac)' + 'LF (Unix/Linux/OS X/BSD)' + ) + Style = csDropDownList + TabOrder = 1 + Text = 'System' + end + object RgDetectContentType: TRadioGroup + Left = 16 + Height = 80 + Top = 156 + Width = 415 + AutoFill = True + Caption = 'Conversion of strings after reading' + ChildSizing.LeftRightSpacing = 6 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.EnlargeVertical = crsHomogenousChildResize + ChildSizing.ShrinkHorizontal = crsScaleChilds + ChildSizing.ShrinkVertical = crsScaleChilds + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 1 + ClientHeight = 60 + ClientWidth = 411 + ItemIndex = 1 + Items.Strings = ( + 'Do not convert, strings are sufficient' + 'Try to convert strings to content types' + ) + TabOrder = 3 + end + object LbEncoding: TLabel + Left = 16 + Height = 15 + Top = 116 + Width = 87 + Caption = 'String encoding:' + FocusControl = CbEncoding + ParentColor = False + end + object CbEncoding: TComboBox + Left = 156 + Height = 23 + Top = 112 + Width = 275 + DropDownCount = 32 + ItemHeight = 15 + Style = csDropDownList + TabOrder = 4 + end + end + object PgNumberParams: TTabSheet + Caption = 'Number cells' + ClientHeight = 471 + ClientWidth = 446 + object CbAutoDetectNumberFormat: TCheckBox + Left = 16 + Height = 19 + Top = 16 + Width = 200 + Caption = 'Try to auto-detect number format' + Checked = True + State = cbChecked + TabOrder = 0 + end + object EdNumFormat: TEdit + Left = 232 + Height = 23 + Top = 140 + Width = 194 + TabOrder = 3 + end + object LblNumFormat: TLabel + Left = 17 + Height = 15 + Top = 144 + Width = 182 + Caption = 'Format string for writing numbers:' + FocusControl = EdNumFormat + ParentColor = False + end + object LblNumFormatInfo: TLabel + Left = 232 + Height = 80 + Top = 176 + Width = 194 + AutoSize = False + BorderSpacing.Left = 8 + BorderSpacing.Right = 8 + BorderSpacing.Around = 8 + Caption = 'If empty, numbers are written in the same format as they appear in the worksheet.' + FocusControl = EdNumFormat + ParentColor = False + WordWrap = True + end + object LblDecimalSeparator: TLabel + Left = 16 + Height = 15 + Top = 59 + Width = 98 + Caption = 'Decimal separator:' + FocusControl = CbDecimalSeparator + ParentColor = False + end + object CbDecimalSeparator: TComboBox + Left = 232 + Height = 23 + Top = 56 + Width = 194 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'like spreadsheet' + 'Period ( . )' + 'Comma ( , )' + ) + TabOrder = 1 + Text = 'like spreadsheet' + end + object LblThousandSeparator: TLabel + Left = 16 + Height = 15 + Top = 91 + Width = 108 + Caption = 'Thousand separator:' + FocusControl = CbThousandSeparator + ParentColor = False + end + object CbThousandSeparator: TComboBox + Left = 232 + Height = 23 + Top = 88 + Width = 194 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'like spreadsheet' + 'Period ( . )' + 'Comma ( , )' + 'Space ( )' + ) + TabOrder = 2 + Text = 'like spreadsheet' + end + end + object PgCurrency: TTabSheet + Caption = 'Currency cells' + ClientHeight = 471 + ClientWidth = 446 + object LblCurrencySymbol: TLabel + Left = 16 + Height = 15 + Top = 20 + Width = 93 + Caption = 'Currency symbol:' + FocusControl = EdCurrencySymbol + ParentColor = False + end + object EdCurrencySymbol: TEdit + Left = 232 + Height = 23 + Top = 16 + Width = 194 + OnEnter = DateTimeFormatChange + TabOrder = 0 + Text = 'like spreadsheet' + end + end + object PgDateTimeParams: TTabSheet + Caption = 'Date/time cells' + ClientHeight = 471 + ClientWidth = 446 + object LblNumFormat1: TLabel + Left = 16 + Height = 15 + Top = 20 + Width = 128 + Caption = 'Long date format string:' + ParentColor = False + end + object LblNumFormat2: TLabel + Left = 16 + Height = 15 + Top = 52 + Width = 129 + Caption = 'Short date format string:' + ParentColor = False + end + object LblDecimalSeparator1: TLabel + Left = 16 + Height = 15 + Top = 83 + Width = 79 + Caption = 'Date separator:' + FocusControl = CbDateSeparator + ParentColor = False + end + object CbDateSeparator: TComboBox + Left = 232 + Height = 23 + Top = 80 + Width = 194 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'like spreadsheet' + 'Dot ( . )' + 'Dash ( - )' + 'Slash ( / )' + ) + OnChange = DateTimeFormatChange + OnEnter = DateTimeFormatChange + TabOrder = 2 + Text = 'like spreadsheet' + end + object LblNumFormat3: TLabel + Left = 16 + Height = 15 + Top = 268 + Width = 129 + Caption = 'Long time format string:' + ParentColor = False + end + object LblNumFormat4: TLabel + Left = 16 + Height = 15 + Top = 300 + Width = 130 + Caption = 'Short time format string:' + ParentColor = False + end + object LblDecimalSeparator2: TLabel + Left = 16 + Height = 15 + Top = 331 + Width = 82 + Caption = 'Time separator:' + FocusControl = CbTimeSeparator + ParentColor = False + end + object CbTimeSeparator: TComboBox + Left = 232 + Height = 23 + Top = 328 + Width = 194 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'like spreadsheet' + 'Dot ( . )' + 'Dash ( - )' + 'Slash ( / )' + 'Colon ( : )' + ) + OnChange = DateTimeFormatChange + OnEnter = DateTimeFormatChange + TabOrder = 5 + Text = 'like spreadsheet' + end + object LblLongMonthNames: TLabel + Left = 16 + Height = 15 + Top = 116 + Width = 107 + Caption = 'Long month names:' + ParentColor = False + end + object LblShortMonthNames: TLabel + Left = 16 + Height = 15 + Top = 148 + Width = 108 + Caption = 'Short month names:' + ParentColor = False + end + object LblLongDayNames: TLabel + Left = 16 + Height = 15 + Top = 180 + Width = 90 + Caption = 'Long day names:' + ParentColor = False + end + object LblShortDayNames: TLabel + Left = 16 + Height = 15 + Top = 212 + Width = 91 + Caption = 'Short day names:' + ParentColor = False + end + object CbLongDateFormat: TComboBox + Left = 232 + Height = 23 + Top = 16 + Width = 194 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'like spreadsheet' + 'ddd, d/mm/yyyy' + 'ddd, d/mmm/yyyy' + 'dddd, d/mm/yyyy' + 'dddd, d/mmm/yyyy' + 'd/mm/yyyy' + 'dd/mm/yyyy' + 'dddd, mm/d/yyyy' + 'dddd, mmm/d/yyyy' + 'mm/d/yyyy' + 'mm/dd/yyyy' + 'yyyy/mm/dd' + 'yyyy/mm/d' + 'yyyy/mmm/d' + 'yyyy/mmmm/d' + ) + OnChange = DateTimeFormatChange + OnEnter = DateTimeFormatChange + TabOrder = 0 + Text = 'like spreadsheet' + end + object CbShortDateFormat: TComboBox + Left = 232 + Height = 23 + Top = 48 + Width = 194 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'like spreadsheet' + 'd/m/yy' + 'd/mm/yy' + 'd/mm/yyyy' + 'm/d/yy' + 'mm/d/yy' + 'mm/d/yyyy' + 'yy/m/d' + 'yy/mm/d' + 'yyyy/mm/d' + ) + OnChange = DateTimeFormatChange + OnEnter = DateTimeFormatChange + TabOrder = 1 + Text = 'like spreadsheet' + end + object CbLongTimeFormat: TComboBox + Left = 232 + Height = 23 + Top = 264 + Width = 194 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'like spreadsheet' + 'h:n:s' + 'h:nn:ss' + 'hh:nn:ss' + ) + OnChange = DateTimeFormatChange + OnEnter = DateTimeFormatChange + TabOrder = 3 + Text = 'like spreadsheet' + end + object CbShortTimeFormat: TComboBox + Left = 232 + Height = 23 + Top = 296 + Width = 194 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'like spreadsheet' + 'h:n' + 'h:nn' + 'hh:nn' + ) + OnChange = DateTimeFormatChange + OnEnter = DateTimeFormatChange + TabOrder = 4 + Text = 'like spreadsheet' + end + object GroupBox1: TGroupBox + Left = 17 + Height = 58 + Top = 366 + Width = 409 + Caption = 'Sample' + ClientHeight = 38 + ClientWidth = 405 + TabOrder = 6 + object LblDateTimeSample: TLabel + Left = 7 + Height = 20 + Top = 2 + Width = 388 + Alignment = taCenter + Anchors = [akTop, akLeft, akRight] + AutoSize = False + Caption = 'sample' + ParentColor = False + end + end + end + object PgBoolParams: TTabSheet + Caption = 'Boolean cells' + ClientHeight = 471 + ClientWidth = 446 + object EdTRUE: TEdit + Left = 16 + Height = 23 + Top = 40 + Width = 131 + TabOrder = 0 + end + object EdFALSE: TEdit + Left = 176 + Height = 23 + Top = 40 + Width = 131 + TabOrder = 1 + end + object Label1: TLabel + Left = 19 + Height = 15 + Top = 16 + Width = 81 + Caption = 'Text for "TRUE"' + ParentColor = False + end + object Label2: TLabel + Left = 179 + Height = 15 + Top = 16 + Width = 85 + Caption = 'Text for "FALSE"' + ParentColor = False + end + end + end +end diff --git a/applications/spready/scsvparamsform.pas b/applications/spready/scsvparamsform.pas new file mode 100644 index 000000000..d5b36df7f --- /dev/null +++ b/applications/spready/scsvparamsform.pas @@ -0,0 +1,594 @@ +unit sCSVParamsForm; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, + ButtonPanel, ExtCtrls, ComCtrls, StdCtrls, + fpsCSV, + sCtrls; + +type + + { TCSVParamsForm } + + TCSVParamsForm = class(TForm) + ButtonPanel: TButtonPanel; + CbAutoDetectNumberFormat: TCheckBox; + CbLongDateFormat: TComboBox; + CbLongTimeFormat: TComboBox; + CbEncoding: TComboBox; + EdCurrencySymbol: TEdit; + CbShortTimeFormat: TComboBox; + CbShortDateFormat: TComboBox; + CbDecimalSeparator: TComboBox; + CbDateSeparator: TComboBox; + CbTimeSeparator: TComboBox; + CbThousandSeparator: TComboBox; + CbLineEnding: TComboBox; + CbQuoteChar: TComboBox; + CbDelimiter: TComboBox; + EdTRUE: TEdit; + EdFALSE: TEdit; + EdNumFormat: TEdit; + GroupBox1: TGroupBox; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + Label4: TLabel; + LblDateTimeSample: TLabel; + LblDecimalSeparator: TLabel; + LblDecimalSeparator1: TLabel; + LblDecimalSeparator2: TLabel; + LblCurrencySymbol: TLabel; + LbEncoding: TLabel; + LblShortMonthNames: TLabel; + LblLongDayNames: TLabel; + LblShortDayNames: TLabel; + LblNumFormat1: TLabel; + LblNumFormat2: TLabel; + LblNumFormat3: TLabel; + LblNumFormat4: TLabel; + LblLongMonthNames: TLabel; + LblThousandSeparator: TLabel; + LblNumFormat: TLabel; + LblQuoteChar: TLabel; + LblNumFormatInfo: TLabel; + PageControl: TPageControl; + PgGeneralParams: TTabSheet; + PgNumberParams: TTabSheet; + PgDateTimeParams: TTabSheet; + PgBoolParams: TTabSheet; + RgDetectContentType: TRadioGroup; + PgCurrency: TTabSheet; + procedure DateTimeFormatChange(Sender: TObject); + procedure FormCloseQuery(Sender: TObject; var CanClose: boolean); + procedure FormCreate(Sender: TObject); + private + { private declarations } + FSampleDateTime: TDateTime; + FDateFormatSample: String; + FTimeFormatSample: String; + FEdLongMonthNames: TMonthDayNamesEdit; + FEdShortMonthNames: TMonthDayNamesEdit; + FEdLongDayNames: TMonthDayNamesEdit; + FEdShortDayNames: TMonthDayNamesEdit; + procedure DateSeparatorToFormatSettings(var ASettings: TFormatSettings); + procedure DecimalSeparatorToFormatSettings(var ASettings: TFormatSettings); +// function GetCurrencySymbol: String; + procedure ThousandSeparatorToFormatSettings(var ASettings: TFormatSettings); + procedure TimeSeparatorToFormatSettings(var ASettings: TFormatSettings); + public + { public declarations } + procedure GetParams(var AParams: TsCSVParams); + procedure SetParams(const AParams: TsCSVParams); + end; + +var + CSVParamsForm: TCSVParamsForm; + +implementation + +{$R *.lfm} + +uses + LConvEncoding, fpsUtils; + +resourcestring + rsLikeSpreadsheet = 'like spreadsheet'; + +var + CSVParamsPageIndex: Integer = 0; + + +{ TCSVParamsForm } + +procedure TCSVParamsForm.DateSeparatorToFormatSettings(var ASettings: TFormatSettings); +begin + case CbDateSeparator.ItemIndex of + 0: ASettings.DateSeparator := #0; + 1: ASettings.DateSeparator := '.'; + 2: ASettings.DateSeparator := '-'; + 3: ASettings.DateSeparator := '/'; + else ASettings.DateSeparator := CbDateSeparator.Text[1]; + end; +end; + +procedure TCSVParamsForm.DecimalSeparatorToFormatSettings(var ASettings: TFormatSettings); +begin + case CbDecimalSeparator.ItemIndex of + 0: ASettings.DecimalSeparator := #0; + 1: ASettings.DecimalSeparator := '.'; + 2: ASettings.DecimalSeparator := ','; + else ASettings.DecimalSeparator := CbDecimalSeparator.Text[1]; + end; +end; + +procedure TCSVParamsForm.DateTimeFormatChange(Sender: TObject); +var + fs: TFormatSettings; + ctrl: TWinControl; + dt: TDateTime; + arr: Array[1..12] of String; + i: Integer; +begin + fs := UTF8FormatSettings; + if CbLongDateFormat.ItemIndex <> 0 then + fs.LongDateFormat := CbLongDateFormat.Text; + if CbShortDateFormat.ItemIndex <> 0 then + fs.ShortDateFormat := CbShortDateFormat.Text; + if CbLongTimeFormat.ItemIndex <> 0 then + fs.LongTimeFormat := CbLongTimeFormat.Text; + if CbShortTimeFormat.ItemIndex <> 0 then + fs.ShortTimeFormat := CbShortTimeFormat.Text; + if CbDateSeparator.ItemIndex <> 0 then + DateSeparatorToFormatSettings(fs); + if CbTimeSeparator.ItemIndex <> 0 then + TimeSeparatorToFormatSettings(fs); + + if FEdLongMonthNames.Text <> rsLikeSpreadsheet then begin + arr[1] := ''; // to silence the compiler + FEdLongMonthNames.GetNames(arr); + for i:=1 to 12 do + if arr[i] <> '' then fs.LongMonthNames[i] := arr[i]; + end; + if FEdShortMonthNames.Text <> rsLikeSpreadsheet then begin + FEdShortMonthNames.GetNames(arr); + for i:=1 to 12 do + if arr[i] <> '' then fs.ShortMonthNames[i] := arr[i]; + end; + if FEdLongDayNames.Text <> rsLikeSpreadsheet then begin + FEdLongDayNames.GetNames(arr); + for i:=1 to 7 do + if arr[i] <> '' then fs.LongDayNames[i] := arr[i]; + end; + if FEdShortDayNames.Text <> rsLikeSpreadsheet then begin + FEdShortDayNames.GetNames(arr); + for i:=1 to 7 do + if arr[i] <> '' then fs.ShortDayNames[i] := arr[i]; + end; + + dt := FSampleDateTime; + ctrl := ActiveControl; + if (ctrl = CbLongDateFormat) then + begin + FDateFormatSample := fs.LongDateFormat; + LblDateTimeSample.Caption := FormatDateTime(FDateFormatSample, dt, fs); + end + else + if (ctrl = CbShortDateFormat) then + begin + FDateFormatSample := fs.ShortDateFormat; + LblDateTimeSample.Caption := FormatDateTime(FDateFormatSample, dt, fs); + end + else + if (ctrl = CbDateSeparator) then + LblDateTimeSample.Caption := FormatDateTime(FDateFormatSample, dt, fs) + else + if (ctrl = CbLongTimeFormat) then + begin + FTimeFormatSample := fs.LongTimeFormat; + LblDateTimeSample.Caption := FormatDateTime(FTimeFormatSample, dt, fs); + end + else + if (ctrl = CbShortTimeFormat) then + begin + FTimeFormatSample := fs.ShortTimeFormat; + LblDateTimeSample.Caption := FormatDateTime(FTimeFormatSample, dt, fs); + end + else + if (ctrl = CbTimeSeparator) then + LblDateTimeSample.Caption := FormatDateTime(FTimeFormatSample, dt, fs) + else + LblDateTimeSample.Caption := FormatDateTime('c', dt, fs); + + Application.ProcessMessages; +end; + +procedure TCSVParamsForm.FormCloseQuery(Sender: TObject; var CanClose: boolean); +begin + Unused(Sender, CanClose); + CSVParamsPageIndex := PageControl.ActivePageIndex; +end; + +procedure TCSVParamsForm.FormCreate(Sender: TObject); +begin + PageControl.ActivePageIndex := CSVParamsPageIndex; + + // Populate encoding combobox. Done in code because of the conditional define. + with CbEncoding.Items do begin + Add('automatic / UTF8'); + Add('UTF8'); + Add('UTF8 with BOM'); + Add('ISO_8859_1 (Central Europe)'); + Add('ISO_8859_15 (Western European languages)'); + Add('ISO_8859_2 (Eastern Europe)'); + Add('CP1250 (Central Europe)'); + Add('CP1251 (Cyrillic)'); + Add('CP1252 (Latin 1)'); + Add('CP1253 (Greek)'); + Add('CP1254 (Turkish)'); + Add('CP1255 (Hebrew)'); + Add('CP1256 (Arabic)'); + Add('CP1257 (Baltic)'); + Add('CP1258 (Vietnam)'); + Add('CP437 (DOS central Europe)'); + Add('CP850 (DOS western Europe)'); + Add('CP852 (DOS central Europe)'); + Add('CP866 (DOS and Windows console''s cyrillic)'); + Add('CP874 (Thai)'); + {$IFNDEF DisableAsianCodePages} + // Asian encodings + Add('CP932 (Japanese)'); + Add('CP936 (Chinese)'); + Add('CP949 (Korea)'); + Add('CP950 (Chinese Complex)'); + {$ENDIF} + Add('KOI8 (Russian cyrillic)'); + Add('UCS2LE (UCS2-LE 2byte little endian)'); + Add('UCS2BE (UCS2-BE 2byte big endian)'); + end; + CbEncoding.ItemIndex := 0; + + FEdLongMonthNames := TMonthDayNamesEdit.Create(self); + with FEdLongMonthNames do + begin + Parent := PgDateTimeParams; + Left := CbDateSeparator.Left; + Top := CbDateSeparator.Top + 32; + {$IFDEF LCL_FULLVERSION AND LCL_FULLVERSION > 1020600} + Width := CbDateSeparator.Width; + {$ELSE} + Width := CbDateSeparator.Width - Button.Width; + {$ENDIF} + OnChange := @DateTimeFormatChange; + OnEnter := @DateTimeFormatChange; + TabOrder := CbDateSeparator.TabOrder + 1; + end; + LblLongMonthNames.FocusControl := FEdLongMonthNames; + + FEdShortMonthNames := TMonthDayNamesEdit.Create(self); + with FEdShortMonthNames do + begin + Parent := PgDateTimeParams; + Left := CbDateSeparator.Left; + Top := CbDateSeparator.Top + 32*2; + Width := FEdLongMonthNames.Width; + TabOrder := CbDateSeparator.TabOrder + 2; + OnChange := @DateTimeFormatChange; + OnEnter := @DateTimeFormatChange; + end; + LblShortMonthNames.FocusControl := FEdShortMonthNames; + + FEdLongDayNames := TMonthDayNamesEdit.Create(self); + with FEdLongDayNames do + begin + Parent := PgDateTimeParams; + Left := CbDateSeparator.Left; + Top := CbDateSeparator.Top + 32*3; + Width := FEdLongMonthNames.Width; + TabOrder := CbDateSeparator.TabOrder + 3; + OnChange := @DateTimeFormatChange; + OnEnter := @DateTimeFormatChange; + end; + LblLongDayNames.FocusControl := FEdLongDayNames; + + FEdShortDayNames := TMonthDayNamesEdit.Create(self); + with FEdShortDayNames do + begin + Parent := PgDateTimeParams; + Left := CbDateSeparator.Left; + Top := CbDateSeparator.Top + 32*4; + Width := FEdLongMonthNames.Width; + TabOrder := CbDateSeparator.TabOrder + 4; + OnChange := @DateTimeFormatChange; + OnEnter := @DateTimeFormatChange; + end; + LblShortDayNames.FocusControl := FEdShortDayNames; + + FDateFormatSample := UTF8FormatSettings.LongDateFormat; + FTimeFormatSample := UTF8FormatSettings.LongTimeFormat; + FSampleDateTime := now(); +end; + +procedure TCSVParamsForm.GetParams(var AParams: TsCSVParams); +var + s: String; +begin + // Line endings + case CbLineEnding.ItemIndex of + 0: AParams.LineEnding := leSystem; + 1: AParams.LineEnding := leCRLF; + 2: AParams.LineEnding := leCR; + 3: AParams.LineEnding := leLF; + end; + + // Column delimiter + case CbDelimiter.ItemIndex of + 0: AParams.Delimiter := ','; + 1: AParams.Delimiter := ';'; + 2: AParams.Delimiter := ':'; + 3: AParams.Delimiter := '|'; + 4: AParams.Delimiter := #9; + end; + + // Quote character + case CbQuoteChar.ItemIndex of + 0: AParams.QuoteChar := #0; + 1: AParams.QuoteChar := '"'; + 2: AParams.QuoteChar := ''''; + end; + + // Encoding + if CbEncoding.ItemIndex = 0 then + AParams.Encoding := '' + else if CbEncoding.ItemIndex = 1 then + AParams.Encoding := EncodingUTF8BOM + else + begin + s := CbEncoding.Items[CbEncoding.ItemIndex]; + AParams.Encoding := Copy(s, 1, Pos(' ', s)-1); + end; + + // Detect content type and convert + AParams.DetectContentType := RgDetectContentType.ItemIndex <> 0; + + // Auto-detect number format + AParams.AutoDetectNumberFormat := CbAutoDetectNumberFormat.Checked; + + // Number format + AParams.NumberFormat := EdNumFormat.Text; + + // Decimal separator + DecimalSeparatorToFormatSettings(AParams.FormatSettings); + + // Thousand separator + ThousandSeparatorToFormatSettings(AParams.FormatSettings); + + // Currency symbol + if (EdCurrencySymbol.Text = '') or (EdCurrencySymbol.Text = rsLikeSpreadsheet) then + AParams.FormatSettings.CurrencyString := '' + else + AParams.FormatSettings.CurrencyString := EdCurrencySymbol.Text; + + // Long date format string + if (CbLongDateFormat.ItemIndex = 0) or (CbLongDateFormat.Text = '') then + AParams.FormatSettings.LongDateFormat := '' + else + AParams.FormatSettings.LongDateFormat := CbLongDateFormat.Text; + + // Short date format string + if (CbShortDateFormat.ItemIndex = 0) or (CbShortDateFormat.Text = '') then + AParams.FormatSettings.ShortDateFormat := '' + else + AParams.FormatSettings.ShortDateFormat := CbShortDateFormat.Text; + + // Date separator + DateSeparatorToFormatSettings(AParams.FormatSettings); + + // Long month names + FEdLongMonthNames.GetNames(AParams.FormatSettings.LongMonthNames); + + // Short month names + FEdShortMonthNames.GetNames(AParams.FormatSettings.ShortMonthNames); + + // Long day names + FEdLongDayNames.GetNames(AParams.FormatSettings.LongDayNames); + + // Short day names + FEdShortDayNames.GetNames(AParams.FormatSettings.ShortDayNames); + + // Long time format string + if CbLongTimeFormat.ItemIndex = 0 then + AParams.FormatSettings.LongTimeFormat := '' + else + AParams.FormatSettings.LongTimeFormat := CbLongTimeFormat.Text; + + // Short time format string + if CbShortTimeFormat.ItemIndex = 0 then + AParams.FormatSettings.ShortTimeFormat := '' + else + AParams.FormatSettings.ShortTimeFormat := CbShortTimeFormat.Text; + + // Time separator + TimeSeparatorToFormatSettings(AParams.FormatSettings); + + // Text for "TRUE" + AParams.TrueText := EdTRUE.Text; + + // Test for "FALSE" + AParams.FalseText := EdFALSE.Text; +end; + +procedure TCSVParamsForm.SetParams(const AParams: TsCSVParams); +var + s: String; + i: Integer; +begin + // Line endings + case AParams.LineEnding of + leSystem: CbLineEnding.ItemIndex := 0; + leCRLF : CbLineEnding.ItemIndex := 1; + leCR : CbLineEnding.ItemIndex := 2; + leLF : CbLineEnding.ItemIndex := 3; + end; + + // Column delimiter + case AParams.Delimiter of + ',' : CbDelimiter.ItemIndex := 0; + ';' : CbDelimiter.ItemIndex := 1; + ':' : CbDelimiter.ItemIndex := 2; + '|' : CbDelimiter.ItemIndex := 3; + #9 : CbDelimiter.ItemIndex := 4; + end; + + // Quote character + case AParams.QuoteChar of + #0 : CbQuoteChar.ItemIndex := 0; + '"' : CbQuoteChar.ItemIndex := 1; + '''' : CbQuoteChar.ItemIndex := 2; + end; + + // String encoding + if AParams.Encoding = '' then + CbEncoding.ItemIndex := 0 + else if AParams.Encoding = EncodingUTF8BOM then + CbEncoding.ItemIndex := 1 + else + for i:=1 to CbEncoding.Items.Count-1 do + begin + s := CbEncoding.Items[i]; + if SameText(AParams.Encoding, Copy(s, 1, Pos(' ', s)-1)) then + begin + CbEncoding.ItemIndex := i; + break; + end; + end; + + // Detect content type + RgDetectContentType.ItemIndex := ord(AParams.DetectContentType); + + // Auto-detect number format + CbAutoDetectNumberFormat.Checked := AParams.AutoDetectNumberFormat; + + // Number format + EdNumFormat.Text := AParams.NumberFormat; + + // Decimal separator + case AParams.FormatSettings.DecimalSeparator of + #0 : CbDecimalSeparator.ItemIndex := 0; + '.' : CbDecimalSeparator.ItemIndex := 1; + ',' : CbDecimalSeparator.ItemIndex := 2; + else CbDecimalSeparator.Text := AParams.FormatSettings.DecimalSeparator; + end; + + // Thousand separator + case AParams.FormatSettings.ThousandSeparator of + #0 : CbThousandSeparator.ItemIndex := 0; + '.' : CbThousandSeparator.ItemIndex := 1; + ',' : CbThousandSeparator.ItemIndex := 2; + ' ' : CbThousandSeparator.ItemIndex := 3; + else CbThousandSeparator.Text := AParams.FormatSettings.ThousandSeparator; + end; + + // Currency symbol + if AParams.FormatSettings.CurrencyString = '' then + EdCurrencySymbol.Text := rsLikeSpreadsheet + else + EdCurrencySymbol.Text := AParams.FormatSettings.CurrencyString; + + // Long date format + if AParams.FormatSettings.LongDateFormat = '' then + CbLongDateFormat.ItemIndex := 0 + else + CbLongDateFormat.Text := AParams.FormatSettings.LongDateFormat; + + // Short date format + if AParams.FormatSettings.ShortDateFormat = '' then + CbShortDateFormat.ItemIndex := 0 + else + CbShortDateFormat.Text := AParams.FormatSettings.ShortDateFormat; + + // Date separator + case AParams.FormatSettings.DateSeparator of + #0 : CbDateSeparator.ItemIndex := 0; + '.' : CbDateSeparator.ItemIndex := 1; + '-' : CbDateSeparator.ItemIndex := 2; + '/' : CbDateSeparator.ItemIndex := 3; + else CbDateSeparator.Text := AParams.FormatSettings.DateSeparator; + end; + + // Long month names + FEdLongMonthNames.SetNames(AParams.FormatSettings.LongMonthNames, 12, false, rsLikeSpreadsheet); + + // Short month names + FEdShortMonthNames.SetNames(AParams.FormatSettings.ShortMonthNames, 12, true, rsLikeSpreadsheet); + + // Long day names + FEdLongDayNames.SetNames(AParams.FormatSettings.LongDayNames, 7, false, rsLikeSpreadsheet); + + // Short month names + FEdShortDayNames.SetNames(AParams.FormatSettings.ShortDayNames, 7, true, rsLikeSpreadsheet); + + // Long time format + if AParams.FormatSettings.LongTimeFormat = '' then + CbLongTimeFormat.ItemIndex := 0 + else + CbLongTimeFormat.Text := AParams.FormatSettings.LongTimeFormat; + + // Short time format + if AParams.FormatSettings.ShortTimeFormat = '' then + CbShortTimeFormat.ItemIndex := 0 + else + CbShortTimeFormat.Text := AParams.FormatSettings.ShortTimeFormat; + + // Time separator + case AParams.FormatSettings.TimeSeparator of + #0 : CbTimeSeparator.ItemIndex := 0; + '.' : CbTimeSeparator.ItemIndex := 1; + '-' : CbTimeSeparator.ItemIndex := 2; + '/' : CbTimeSeparator.ItemIndex := 3; + ':' : CbTimeSeparator.ItemIndex := 4; + else CbTimeSeparator.Text := AParams.FormatSettings.TimeSeparator; + end; + + // Text for "TRUE" + EdTRUE.Text := AParams.TrueText; + + // Test for "FALSE" + EdFALSE.Text := AParams.FalseText; + + // Update date/time sample display + DateTimeFormatChange(nil); +end; + +procedure TCSVParamsForm.ThousandSeparatorToFormatSettings(var ASettings: TFormatSettings); +begin + case CbThousandSeparator.ItemIndex of + 0: ASettings.ThousandSeparator := #0; + 1: ASettings.ThousandSeparator := '.'; + 2: ASettings.ThousandSeparator := ','; + 3: ASettings.ThousandSeparator := ' '; + else ASettings.ThousandSeparator := CbThousandSeparator.Text[1]; + end; +end; + +procedure TCSVParamsForm.TimeSeparatorToFormatSettings(var ASettings: TFormatSettings); +begin + case CbTimeSeparator.ItemIndex of + 0: ASettings.TimeSeparator := #0; + 1: ASettings.TimeSeparator := '.'; + 2: ASettings.TimeSeparator := '-'; + 3: ASettings.TimeSeparator := '/'; + 4: ASettings.TimeSeparator := ':'; + else ASettings.TimeSeparator := CbTimeSeparator.Text[1]; + end; +end; + +//initialization +// {$I scsvparamsform.lrs} + +end. + diff --git a/applications/spready/sctrls.pas b/applications/spready/sctrls.pas new file mode 100644 index 000000000..680e37138 --- /dev/null +++ b/applications/spready/sctrls.pas @@ -0,0 +1,326 @@ +unit sCtrls; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Controls, StdCtrls, Grids, EditBtn, Forms; + +type + { TMonthDayNamesEdit } + TMonthDayNamesEdit = class(TEditButton) + private + FEmptyString: String; + FCount: Integer; + FShortnames: Boolean; + procedure ButtonClickHandler(Sender: TObject); + function CreateMonthDayNamesEditor(var AGrid: TStringGrid): TForm; + protected + public + constructor Create(AOwner: TComponent); override; + procedure GetNames(var ANamesArray); + procedure SetNames(const ANamesArray; ACount: Integer; IsShortNames: Boolean; + const AEmptyString: String); + end; + + { TFormatSeparatorCombo } + TFormatSeparatorKind = (skDecimal, skThousand, skDate, skTime, skList); + + TFormatSeparatorCombo = class(TCombobox) + private + FKind: TFormatSeparatorKind; + function GetSeparator: Char; + procedure SetSeparator(AValue: Char); + procedure SetSeparatorKind(AValue: TFormatSeparatorKind); + public + property Separator: Char read GetSeparator write SetSeparator; + property SeparatorKind: TFormatSeparatorKind read FKind write SetSeparatorKind; + end; + + +implementation + +uses + Math, ButtonPanel, fpsUtils; + +{@@ ---------------------------------------------------------------------------- + Concatenates the day names specified in ADayNames to a single string. If all + daynames are empty AEmptyStr is returned + + @param ADayNames Array[1..7] of day names as used in the Formatsettings + @param AEmptyStr Is returned if all day names are empty + @return String having all day names concatenated and separated by the + DefaultFormatSettings.ListSeparator +-------------------------------------------------------------------------------} +function DayNamesToString(const ADayNames: TWeekNameArray; + const AEmptyStr: String): String; +var + i: Integer; + isEmpty: Boolean; +begin + isEmpty := true; + for i:=1 to 7 do + if ADayNames[i] <> '' then + begin + isEmpty := false; + break; + end; + + if isEmpty then + Result := AEmptyStr + else + begin + Result := ADayNames[1]; + for i:=2 to 7 do + Result := Result + DefaultFormatSettings.ListSeparator + ' ' + ADayNames[i]; + end; +end; + +{@@ ---------------------------------------------------------------------------- + Concatenates the month names specified in AMonthNames to a single string. + If all month names are empty AEmptyStr is returned + + @param AMonthNames Array[1..12] of month names as used in the Formatsettings + @param AEmptyStr Is returned if all month names are empty + @return String having all month names concatenated and separated by the + DefaultFormatSettings.ListSeparator +-------------------------------------------------------------------------------} +function MonthNamesToString(const AMonthNames: TMonthNameArray; + const AEmptyStr: String): String; +var + i: Integer; + isEmpty: Boolean; +begin + isEmpty := true; + for i:=1 to 12 do + if AMonthNames[i] <> '' then + begin + isEmpty := false; + break; + end; + + if isEmpty then + Result := AEmptyStr + else + begin + Result := AMonthNames[1]; + for i:=2 to 12 do + Result := Result + DefaultFormatSettings.ListSeparator + ' ' + AMonthNames[i]; + end; +end; + +{ TMonthDayNamesEdit } + +constructor TMonthDayNamesEdit.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + Button.Caption := '...'; + OnButtonClick := @ButtonClickHandler; +end; + +procedure TMonthDayNamesEdit.ButtonClickHandler(Sender: TObject); +var + F: TForm; + i: Integer; + grid: TStringGrid = nil; + names: TMonthNameArray; // can hold day and month names as well +begin + F := CreateMonthDayNamesEditor(grid); + try + if F.ShowModal = mrOK then + begin + for i:=1 to 12 do + names[i] := ''; + for i:=1 to grid.RowCount-1 do + names[i] := grid.Cells[1, i]; + SetNames(names, FCount, FShortNames, FEmptyString); + end; + finally + F.Free; + end; +end; + +function TMonthDayNamesEdit.CreateMonthDayNamesEditor(var AGrid: TStringGrid): TForm; +var + btnPanel: TButtonPanel; + i: Integer; + R: TRect; + Pt: TPoint; + w: Integer; + names: TMonthNameArray; // has space for both months and days... +begin + Result := TForm.Create(nil); + btnPanel := TButtonPanel.Create(Result); + with btnPanel do begin + Parent := Result; + ShowButtons := [pbOK, pbCancel]; + end; + AGrid := TStringGrid.Create(Result); + with AGrid do begin + Parent := Result; + Align := alClient; + BorderSpacing.Around := 8; + TitleStyle := tsNative; + Options := Options + [goEditing, goAlwaysShowEditor] - [goVertLine]; + DefaultColWidth := 150; + AutoFillColumns := true; + ColCount := 2; + RowCount := FCount+1; + if FCount = 12 then + begin + Cells[0, 1] := 'January'; + Cells[0, 2] := 'February'; + Cells[0, 3] := 'March'; + Cells[0, 4] := 'April'; + Cells[0, 5] := 'May'; + Cells[0, 6] := 'June'; + Cells[0, 7] := 'July'; + Cells[0, 8] := 'August'; + Cells[0, 9] := 'September'; + Cells[0,10] := 'October'; + Cells[0,11] := 'November'; + Cells[0,12] := 'December'; + if FShortNames then + Cells[1, 0] := 'Short month names' + else + Cells[1, 0] := 'Long month names'; + end else + begin + Cells[0, 1] := 'Sunday'; + Cells[0, 2] := 'Monday'; + Cells[0, 3] := 'Tuesday'; + Cells[0, 4] := 'Wesdnesday'; + Cells[0, 5] := 'Thursday'; + Cells[0, 6] := 'Friday'; + Cells[0, 7] := 'Saturday'; + if FShortNames then + Cells[1, 0] := 'Short day names' + else + Cells[1, 0] := 'Long day names'; + end; + names[1] := ''; // to silence the compiler... + GetNames(names); + w := 0; + for i:=1 to FCount do + begin + Cells[1, i] := TMonthNameArray(names)[i]; + w := Max(w, Canvas.TextWidth(Cells[0, i])); + end; + ColWidths[0] := w + 16; + ColWidths[1] := 2*w; + R := CellRect(ColCount-1, RowCount-1); + end; + Pt := Result.ScreenToClient(AGrid.ClientToScreen(R.BottomRight)); + Result.Width := AGrid.width + AGrid.BorderSpacing.Around*2 + 5; + Result.Height := Pt.Y + btnPanel.Height + AGrid.BorderSpacing.Around*2 - 6; + Result.Position := poMainFormCenter; + Result.ActiveControl := AGrid; +end; + +procedure TMonthDayNamesEdit.GetNames(var ANamesArray); +{ Not very nice code here: will crash if a TWeekNameArray is passed as ANameArray, + but the edit stores month data! Watch out... } +var + L: TStringList; + i: Integer; +begin + for i:=1 to FCount do + TMonthNameArray(ANamesArray)[i] := ''; + if Text <> FEmptyString then + begin + L := TStringList.Create; + try + L.Delimiter := DefaultFormatSettings.ListSeparator; + L.DelimitedText := Text; + for i:=0 to L.Count-1 do + if i < L.Count then + TMonthNameArray(ANamesArray)[i+1] := L[i]; + finally + L.Free; + end; + end; +end; + +procedure TMonthDayNamesEdit.SetNames(const ANamesArray; ACount: Integer; + IsShortNames: Boolean; const AEmptyString: String); +begin + if not ACount in [7, 12] then + raise Exception.Create('[TMonthDayNameEdit] Array length can only be 7 or 12.'); + + FCount := ACount; + FEmptyString := AEmptyString; + FShortNames := IsShortNames; + + case FCount of + 7: Text := DayNamesToString(TWeekNameArray(ANamesArray), AEmptyString); + 12: Text := MonthNamesToString(TMonthNameArray(ANamesArray), AEmptyString); + else raise Exception.Create('[TMonthDayNameEdit] Array length can only be 7 or 12.'); + end; +end; + + +{ TFormatSeparatorCombo } + +function TFormatSeparatorCombo.GetSeparator: Char; +begin + if ItemIndex = -1 then + begin + if Text = '' then + Result := #0 + else + Result := Text[1]; + end else + Result := Char(PtrInt(items.Objects[ItemIndex])); +end; + +procedure TFormatSeparatorCombo.SetSeparator(AValue: Char); +var + i: Integer; +begin + i := Items.IndexOfObject(TObject(PtrInt(ord(AValue)))); + if i = -1 then + Text := AValue + else + ItemIndex := i; +end; + +procedure TFormatSeparatorCombo.SetSeparatorKind(AValue: TFormatSeparatorKind); +begin + FKind := AValue; + Items.BeginUpdate; + try + case FKind of + skDecimal, skThousand: + begin + Items.AddObject('Dot ( . )', TObject(PtrInt(ord('.')))); + Items.AddObject('Comma ( , )', TObject(PtrInt(ord(',')))); + if FKind = skThousand then + Items.AddObject('Space ( )', TObject(PtrInt(ord(' ')))); + end; + skDate, skTime: + begin + Items.AddObject('Dot ( . )', TObject(PtrInt(ord('.')))); + Items.AddObject('Dash ( - )', TObject(PtrInt(ord('-')))); + Items.AddObject('Slash ( / )', TObject(PtrInt(ord('/')))); + if FKind = skTime then + Items.AddObject('Colon ( : )', TObject(PtrInt(ord(':')))); + end; + skList: + begin + Items.AddObject('Dot ( . )', TObject(PtrInt(ord('.')))); + Items.AddObject('Comma ( , )', TObject(PtrInt(ord(',')))); + Items.AddObject('Semicolon ( ; )', TObject(PtrInt(ord(';')))); + Items.AddObject('Colon ( : )', TObject(PtrInt(ord(':')))); + Items.AddObject('Bar ( | )', TObject(PtrInt(ord('|')))); + Items.AddObject('Slash ( / )', TObject(PtrInt(ord('/')))); + Items.AddObject('Backslash ( \ )', TObject(PtrInt(ord('\')))); + end; + end; + finally + Items.EndUpdate; + end; +end; + +end. + diff --git a/applications/spready/scurrencyform.lfm b/applications/spready/scurrencyform.lfm new file mode 100644 index 000000000..86b255151 --- /dev/null +++ b/applications/spready/scurrencyform.lfm @@ -0,0 +1,172 @@ +object CurrencyForm: TCurrencyForm + Left = 544 + Height = 288 + Top = 339 + Width = 245 + BorderStyle = bsDialog + Caption = 'Currency symbols' + ClientHeight = 288 + ClientWidth = 245 + OnCreate = FormCreate + ShowHint = True + LCLVersion = '1.5' + object LblInfo: TLabel + Left = 4 + Height = 15 + Top = 4 + Width = 237 + Align = alTop + BorderSpacing.Around = 4 + Caption = 'These strings indicate currencies:' + ParentColor = False + WordWrap = True + end + object CurrencyListbox: TListBox + Left = 4 + Height = 223 + Top = 23 + Width = 237 + Align = alClient + BorderSpacing.Around = 4 + ItemHeight = 0 + TabOrder = 0 + end + object ButtonPanel: TPanel + Left = 0 + Height = 38 + Top = 250 + Width = 245 + Align = alBottom + ClientHeight = 38 + ClientWidth = 245 + FullRepaint = False + TabOrder = 1 + object BtnOK: TBitBtn + Left = 77 + Height = 25 + Hint = 'Accept changes and close' + Top = 8 + Width = 75 + Anchors = [akTop, akRight] + DefaultCaption = True + Kind = bkOK + ModalResult = 1 + OnClick = BtnOKClick + TabOrder = 0 + end + object BtnCancel: TBitBtn + Left = 157 + Height = 25 + Hint = 'Discard changes and close' + Top = 8 + Width = 83 + Anchors = [akTop, akRight] + DefaultCaption = True + Kind = bkCancel + ModalResult = 2 + TabOrder = 1 + end + object ButtonBevel: TBevel + Left = 5 + Height = 3 + Top = 1 + Width = 235 + Align = alTop + BorderSpacing.Left = 4 + BorderSpacing.Right = 4 + Shape = bsTopLine + end + object BtnAdd: TBitBtn + Left = 8 + Height = 25 + Hint = 'Add a currency symbol' + Top = 8 + Width = 27 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0041924E233D8F497D3A8C44DB368940F332873CF32F84 + 37DB2C81337D287F3023FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0049995853459653E6419950FF7DC28FFF96D0A6FF96CFA6FF78BE + 89FF368D42FF2C8134E6297F3053FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00519F61534D9C5DF464B478FFA8DBB5FF87CC98FF66BC7DFF64BA7CFF86CB + 98FFA5D9B4FF58AA6BFF2C8134F4297F3053FFFFFF00FFFFFF00FFFFFF0059A6 + 6B2256A366E56AB97DFFA8DBB2FF60BC77FF5CBA73FF59B870FF59B56FFF58B5 + 6FFF5BB774FFA5D9B3FF5AAA6CFF2C8234E5297F3022FFFFFF00FFFFFF005DA9 + 707E53AB68FFAADDB4FF64C179FF5FBE71FF60BC77FFFFFFFFFFFFFFFFFF59B8 + 70FF58B56EFF5CB774FFA6DAB4FF388F43FF2C82347EFFFFFF00FFFFFF0061AC + 75DB8ACC98FF89D396FF6BC67AFF63C170FF55AB65FFFFFFFFFFFFFFFFFF59B8 + 70FF59B870FF5BB972FF85CC97FF7BBE8DFF308539DBFFFFFF00FFFFFF0065AF + 7AF6A9DDB3FF7DCF8AFF75CC81FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF67BE7DFF9CD4ABFF34883DF6FFFFFF00FFFFFF0069B2 + 7EF6B6E2BEFF8BD597FF7AC986FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF69C17EFF9DD4AAFF388B42F6FFFFFF00FFFFFF006DB5 + 83DBACDDB6FFA6DFAFFF81CB8CFF7CC986FF6EBD79FFFFFFFFFFFFFFFFFF5BAC + 6AFF60BC77FF5CBA73FF8BD199FF80C592FF3C8E47DBFFFFFF00FFFFFF0070B8 + 877E85C797FFD2EED7FF95D9A0FF8AD394FF7FC889FFFFFFFFFFFFFFFFFF79CD + 85FF6BC37CFF6FC77EFFACDFB5FF459E57FF40914C7EFFFFFF00FFFFFF0073BA + 8A2270B887E5AADAB7FFD8F1DCFF92D89DFF88CD93FF84CC8EFF8BD496FF8AD4 + 95FF83D28EFFAFE0B7FF6BB97DFF489856E544945122FFFFFF00FFFFFF00FFFF + FF0073BB8B5370B887F4AFDCBBFFDCF2E0FFB6E4BDFF9BDBA5FF96D9A0FFA5DF + AFFFC0E8C5FF79C28AFF509E5FF44C9B5B53FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0073BB8B5371B887E694CEA4FFC3E6CBFFCFEBD4FFC9E9CEFFAFDD + B8FF6DB97FFF58A569E654A16553FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0074BB8B2371B9887D6EB684DB6AB380F367B17CF363AE + 77DB60AB737D5CA86E23FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = BtnAddClick + Spacing = 0 + TabOrder = 2 + end + object BtnDelete: TBitBtn + Left = 40 + Height = 25 + Hint = 'Delete selected currency symbol' + Top = 8 + Width = 27 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF003F54C3233A50C27D3853BEDB3551BDF3304BBCF32E4E + B8DB2B4CB77D2748B523FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF004658C8534255C6E63C52CCFF757AE8FF8F92EEFF8F92EEFF7178 + E4FF334DC1FF2B4AB7E6294BB553FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF004D5ACD534959CBF45C65E0FFA1A6F5FF7E86EFFF5B63E9FF595DE7FF7D84 + EEFF9EA0F4FF515DD7FF2B4AB7F4294BB553FFFFFF00FFFFFF00FFFFFF00545F + D2225361CFE5616BE3FFA1ACF5FF545FECFF505CEAFF4D59E9FF4E59E6FF4C56 + E6FF5056E6FF9EA2F4FF5460D6FF2A4AB8E5294BB522FFFFFF00FFFFFF005860 + D47E4B56DBFFA2ABF6FF5664F0FF5266EEFF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4C58E6FF525AE6FF9FA3F5FF3450C4FF2A4AB87EFFFFFF00FFFFFF005C62 + D7DB818CEEFF7E91F7FF5D73F3FF4D59E9FF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4D59E9FF4F5BE9FF7B83F0FF757BE2FF2E4BBADBFFFFFF00FFFFFF005F63 + DAF6A1ABF7FF7086F8FF6882F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5C66EAFF969CF1FF3250BCF6FFFFFF00FFFFFF006469 + DBF6AFB9F9FF7F93FAFF7085F0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5E6AEEFF969DF1FF364FBEF6FFFFFF00FFFFFF00676A + DEDBA5AFF5FF9DABFAFF778CF0FF545FECFF545FECFF545FECFF545FECFF545F + ECFF545FECFF6377F2FF818EF4FF787FE9FF3A53C0DBFFFFFF00FFFFFF006A69 + E07E7D83EAFFCDD4FCFF8B9DFAFF7E93F7FF758AEEFF6C84F6FF6C84F6FF6C84 + F6FF6C84F6FF6379F3FFA4AFF8FF3E4FD0FF3E54C27EFFFFFF00FFFFFF006C6C + E1226A69E0E5A3A7F3FFD4DBFDFF879AFAFF7F91F0FF7A8EF1FF7F94F8FF7E92 + F9FF768CF8FFA8B6F8FF636EE3FF4557C7E54156C522FFFFFF00FFFFFF00FFFF + FF006D6CE3536A69E0F4AAADF2FFD8DCFDFFAEBAFAFF91A3FAFF8B9DFAFF9CA9 + FBFFBAC7FCFF707BE9FF4C5BCCF44858CA53FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF006D6CE3536A6ADFE68E93EDFFBEC3F8FFCCD3F9FFC4CBF9FFAAB4 + F4FF6670E2FF535ED1E6505DCE53FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF006D6DE2236B6AE17D686ADDDB6364DCF36164DAF35D63 + D9DB5B63D67D5862D423FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = BtnDeleteClick + Spacing = 0 + TabOrder = 3 + end + end +end diff --git a/applications/spready/scurrencyform.pas b/applications/spready/scurrencyform.pas new file mode 100644 index 000000000..48c596d71 --- /dev/null +++ b/applications/spready/scurrencyform.pas @@ -0,0 +1,100 @@ +unit scurrencyform; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, + ExtCtrls, Buttons; + +type + + { TCurrencyForm } + + TCurrencyForm = class(TForm) + ButtonBevel: TBevel; + BtnAdd: TBitBtn; + BtnCancel: TBitBtn; + BtnDelete: TBitBtn; + BtnOK: TBitBtn; + CurrencyListbox: TListBox; + LblInfo: TLabel; + ButtonPanel: TPanel; + procedure BtnAddClick(Sender: TObject); + procedure BtnDeleteClick(Sender: TObject); + procedure BtnOKClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + private + { private declarations } + function GetCurrencySymbol: String; + procedure SetCurrencySymbol(const AValue: String); + public + { public declarations } + property CurrencySymbol: String read GetCurrencySymbol write SetCurrencySymbol; + end; + +var + CurrencyForm: TCurrencyForm; + +implementation + +{$R *.lfm} + +uses + fpsCurrency; + + +{ TCurrencyForm } + +procedure TCurrencyForm.BtnAddClick(Sender: TObject); +var + s: String; + i: Integer; +begin + s := InputBox('Input', 'Currency symbol:', ''); + if s <> '' then begin + i := CurrencyListbox.Items.IndexOf(s); + if i = -1 then + i := CurrencyListbox.Items.Add(s); + CurrencyListbox.ItemIndex := i; + end; +end; + +procedure TCurrencyForm.BtnDeleteClick(Sender: TObject); +begin + if CurrencyListbox.ItemIndex > -1 then + CurrencyListbox.Items.Delete(CurrencyListbox.ItemIndex); +end; + +procedure TCurrencyForm.BtnOKClick(Sender: TObject); +begin + RegisterCurrencies(CurrencyListbox.Items, true); +end; + +procedure TCurrencyForm.FormCreate(Sender: TObject); +begin + GetRegisteredCurrencies(CurrencyListbox.Items); + CurrencyListbox.ItemIndex := CurrencyListbox.Items.Count-1; +end; + +function TCurrencyForm.GetCurrencySymbol: String; +var + index: Integer; +begin + index := CurrencyListbox.ItemIndex; + if index > -1 then + Result := CurrencyListbox.Items[index] + else + Result := ''; +end; + +procedure TCurrencyForm.SetCurrencySymbol(const AValue: String); +begin + CurrencyListbox.ItemIndex := CurrencyListbox.Items.IndexOf(AValue); +end; + +end. + + + diff --git a/applications/spready/sformatsettingsform.lfm b/applications/spready/sformatsettingsform.lfm new file mode 100644 index 000000000..387df0b60 --- /dev/null +++ b/applications/spready/sformatsettingsform.lfm @@ -0,0 +1,394 @@ +object FormatSettingsForm: TFormatSettingsForm + Left = 417 + Height = 494 + Top = 229 + Width = 470 + BorderStyle = bsDialog + Caption = 'Workbook format settings' + ClientHeight = 494 + ClientWidth = 470 + OnCloseQuery = FormCloseQuery + OnCreate = FormCreate + Position = poMainFormCenter + ShowHint = True + LCLVersion = '1.5' + object PageControl: TPageControl + Left = 8 + Height = 438 + Top = 8 + Width = 454 + ActivePage = PgCurrency + Align = alClient + BorderSpacing.Around = 8 + TabIndex = 1 + TabOrder = 0 + OnChange = PageControlChange + object PgNumber: TTabSheet + Caption = 'Number' + ClientHeight = 410 + ClientWidth = 446 + object LblDecimalSeparator: TLabel + Left = 16 + Height = 15 + Top = 19 + Width = 98 + Caption = 'Decimal separator:' + ParentColor = False + end + object LblThousandSeparator: TLabel + Left = 16 + Height = 15 + Top = 51 + Width = 108 + Caption = 'Thousand separator:' + ParentColor = False + end + object Label1: TLabel + Left = 4 + Height = 15 + Top = 391 + Width = 438 + Align = alBottom + BorderSpacing.Around = 4 + Caption = 'The current workbook is automatically updated to these settings.' + ParentColor = False + WordWrap = True + end + object Bevel3: TBevel + Left = 0 + Height = 3 + Top = 384 + Width = 446 + Align = alBottom + Shape = bsBottomLine + end + end + object PgCurrency: TTabSheet + Caption = 'Currency' + ClientHeight = 410 + ClientWidth = 446 + object LblCurrencySymbol: TLabel + Left = 16 + Height = 15 + Top = 20 + Width = 93 + Caption = 'Currency symbol:' + FocusControl = EdCurrencySymbol + ParentColor = False + end + object EdCurrencySymbol: TEdit + Left = 200 + Height = 23 + Top = 16 + Width = 202 + Anchors = [akTop, akLeft, akRight] + OnChange = EdCurrencySymbolChange + TabOrder = 0 + end + object LblCurrencySymbol1: TLabel + Left = 16 + Height = 15 + Top = 52 + Width = 132 + Caption = 'Currency decimal places:' + FocusControl = EdCurrencyDecimals + ParentColor = False + end + object EdCurrencyDecimals: TSpinEdit + Left = 200 + Height = 23 + Top = 48 + Width = 66 + TabOrder = 1 + end + object LblPosCurrencyFormat: TLabel + Left = 16 + Height = 15 + Top = 84 + Width = 135 + Caption = 'Format of positive values:' + FocusControl = CbPosCurrencyFormat + ParentColor = False + end + object CbPosCurrencyFormat: TComboBox + Left = 200 + Height = 23 + Top = 80 + Width = 231 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + Style = csDropDownList + TabOrder = 2 + end + object LblNegCurrencyFormat: TLabel + Left = 16 + Height = 15 + Top = 116 + Width = 139 + Caption = 'Format of negative values:' + FocusControl = CbNegCurrencyFormat + ParentColor = False + end + object CbNegCurrencyFormat: TComboBox + Left = 200 + Height = 23 + Top = 112 + Width = 231 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + Style = csDropDownList + TabOrder = 3 + end + object Label2: TLabel + Left = 4 + Height = 15 + Top = 391 + Width = 438 + Align = alBottom + BorderSpacing.Around = 4 + Caption = 'These settings are only respected in new cells.' + ParentColor = False + WordWrap = True + end + object Bevel2: TBevel + Left = 0 + Height = 3 + Top = 384 + Width = 446 + Align = alBottom + Shape = bsBottomLine + end + object BtnCurrency: TBitBtn + Left = 406 + Height = 25 + Top = 15 + Width = 25 + Caption = '...' + OnClick = BtnCurrencyClick + TabOrder = 4 + end + end + object PgDateTime: TTabSheet + Caption = 'Date/time' + ClientHeight = 401 + ClientWidth = 446 + object LblNumFormat1: TLabel + Left = 16 + Height = 20 + Top = 20 + Width = 160 + Caption = 'Long date format string:' + ParentColor = False + end + object CbLongDateFormat: TComboBox + Left = 200 + Height = 23 + Top = 16 + Width = 231 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'ddd, d/mm/yyyy' + 'ddd, d/mmm/yyyy' + 'dddd, d/mm/yyyy' + 'dddd, d/mmm/yyyy' + 'd/mm/yyyy' + 'dd/mm/yyyy' + 'dddd, mm/d/yyyy' + 'dddd, mmm/d/yyyy' + 'mm/d/yyyy' + 'mm/dd/yyyy' + 'yyyy/mm/dd' + 'yyyy/mm/d' + 'yyyy/mmm/d' + 'yyyy/mmmm/d' + ) + OnChange = DateTimeFormatChange + OnEnter = DateTimeFormatChange + TabOrder = 0 + Text = 'ddd, d/mm/yyyy' + end + object LblNumFormat2: TLabel + Left = 16 + Height = 20 + Top = 52 + Width = 162 + Caption = 'Short date format string:' + ParentColor = False + end + object CbShortDateFormat: TComboBox + Left = 200 + Height = 23 + Top = 48 + Width = 231 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'd/m/yy' + 'd/mm/yy' + 'd/mm/yyyy' + 'm/d/yy' + 'mm/d/yy' + 'mm/d/yyyy' + 'yy/m/d' + 'yy/mm/d' + 'yyyy/mm/d' + ) + OnChange = DateTimeFormatChange + OnEnter = DateTimeFormatChange + TabOrder = 1 + Text = 'd/m/yy' + end + object LblDateSeparator: TLabel + Left = 16 + Height = 20 + Top = 83 + Width = 102 + Caption = 'Date separator:' + ParentColor = False + end + object LblLongMonthNames: TLabel + Left = 16 + Height = 20 + Top = 116 + Width = 130 + Caption = 'Long month names:' + ParentColor = False + end + object LblShortMonthNames: TLabel + Left = 16 + Height = 20 + Top = 148 + Width = 132 + Caption = 'Short month names:' + ParentColor = False + end + object LblLongDayNames: TLabel + Left = 16 + Height = 20 + Top = 180 + Width = 111 + Caption = 'Long day names:' + ParentColor = False + end + object LblShortDayNames: TLabel + Left = 16 + Height = 20 + Top = 212 + Width = 113 + Caption = 'Short day names:' + ParentColor = False + end + object LblNumFormat3: TLabel + Left = 16 + Height = 20 + Top = 252 + Width = 160 + Caption = 'Long time format string:' + ParentColor = False + end + object LblNumFormat4: TLabel + Left = 16 + Height = 20 + Top = 284 + Width = 162 + Caption = 'Short time format string:' + ParentColor = False + end + object LblTimeSeparator: TLabel + Left = 16 + Height = 20 + Top = 315 + Width = 103 + Caption = 'Time separator:' + ParentColor = False + end + object CbLongTimeFormat: TComboBox + Left = 200 + Height = 23 + Top = 248 + Width = 231 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + ItemIndex = 1 + Items.Strings = ( + 'h:n:s' + 'h:nn:ss' + 'hh:nn:ss' + ) + OnChange = DateTimeFormatChange + OnEnter = DateTimeFormatChange + TabOrder = 2 + Text = 'h:nn:ss' + end + object CbShortTimeFormat: TComboBox + Left = 200 + Height = 23 + Top = 280 + Width = 231 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + ItemIndex = 1 + Items.Strings = ( + 'h:n' + 'h:nn' + 'hh:nn' + ) + OnChange = DateTimeFormatChange + OnEnter = DateTimeFormatChange + TabOrder = 3 + Text = 'h:nn' + end + object Label3: TLabel + Left = 4 + Height = 40 + Top = 357 + Width = 438 + Align = alBottom + BorderSpacing.Around = 4 + Caption = 'Only the date and time separator are automatically respected by the workbook; the other settings are considered only for new cells.' + ParentColor = False + WordWrap = True + end + object Bevel1: TBevel + Left = 0 + Height = 3 + Top = 350 + Width = 446 + Align = alBottom + Shape = bsBottomLine + end + end + end + object ButtonPanel: TButtonPanel + Left = 6 + Height = 34 + Top = 454 + Width = 458 + OKButton.Name = 'OKButton' + OKButton.DefaultCaption = True + OKButton.OnClick = OKButtonClick + HelpButton.Name = 'HelpButton' + HelpButton.DefaultCaption = True + CloseButton.Name = 'CloseButton' + CloseButton.DefaultCaption = True + CancelButton.Name = 'CancelButton' + CancelButton.DefaultCaption = True + TabOrder = 1 + ShowButtons = [pbOK, pbCancel] + object LblDateTimeSample: TLabel + Left = 6 + Height = 36 + Top = 2 + Width = 287 + Anchors = [akTop, akLeft, akRight] + AutoSize = False + Caption = 'sample' + Layout = tlCenter + ParentColor = False + WordWrap = True + end + end +end diff --git a/applications/spready/sformatsettingsform.pas b/applications/spready/sformatsettingsform.pas new file mode 100644 index 000000000..5b464abf0 --- /dev/null +++ b/applications/spready/sformatsettingsform.pas @@ -0,0 +1,470 @@ +unit sFormatsettingsForm; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, + ButtonPanel, ComCtrls, StdCtrls, Spin, ExtCtrls, Buttons, sCtrls; + +type + { TFormatSettingsForm } + + TFormatSettingsForm = class(TForm) + Bevel1: TBevel; + Bevel2: TBevel; + Bevel3: TBevel; + BtnCurrency: TBitBtn; + ButtonPanel: TButtonPanel; + CbLongDateFormat: TComboBox; + CbLongTimeFormat: TComboBox; + CbPosCurrencyFormat: TComboBox; + CbNegCurrencyFormat: TComboBox; + CbShortDateFormat: TComboBox; + CbShortTimeFormat: TComboBox; + EdCurrencySymbol: TEdit; + EdCurrencyDecimals: TSpinEdit; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + LblCurrencySymbol: TLabel; + LblCurrencySymbol1: TLabel; + LblDateTimeSample: TLabel; + LblDecimalSeparator: TLabel; + LblDateSeparator: TLabel; + LblTimeSeparator: TLabel; + LblLongDayNames: TLabel; + LblLongMonthNames: TLabel; + LblNumFormat1: TLabel; + LblNumFormat2: TLabel; + LblNumFormat3: TLabel; + LblNumFormat4: TLabel; + LblPosCurrencyFormat: TLabel; + LblNegCurrencyFormat: TLabel; + LblShortDayNames: TLabel; + LblShortMonthNames: TLabel; + LblThousandSeparator: TLabel; + PageControl: TPageControl; + PgCurrency: TTabSheet; + PgDateTime: TTabSheet; + PgNumber: TTabSheet; + procedure BtnCurrencyClick(Sender: TObject); + procedure DateTimeFormatChange(Sender: TObject); + procedure EdCurrencySymbolChange(Sender: TObject); + procedure FormCloseQuery(Sender: TObject; var CanClose: boolean); + procedure FormCreate(Sender: TObject); + procedure OKButtonClick(Sender: TObject); + procedure PageControlChange(Sender: TObject); + private + FSampleDateTime: TDateTime; + FDateFormatSample: String; + FTimeFormatSample: String; + FEdLongMonthNames: TMonthDayNamesEdit; + FEdShortMonthNames: TMonthDayNamesEdit; + FEdLongDayNames: TMonthDayNamesEdit; + FEdShortDayNames: TMonthDayNamesEdit; + FCbDecimalSeparator: TFormatSeparatorCombo; + FCbThousandSeparator: TFormatSeparatorCombo; + FCbDateSeparator: TFormatSeparatorCombo; + FCbTimeSeparator: TFormatSeparatorCombo; + function GetFormatSettings: TFormatSettings; + procedure SetFormatSettings(const AValue: TFormatSettings); + function ValidData(out AControl: TWinControl; out AMsg: String): Boolean; + public + { public declarations } + property FormatSettings: TFormatSettings read GetFormatSettings write SetFormatSettings; + end; + +var + FormatSettingsForm: TFormatSettingsForm; + + +implementation + +{$R *.lfm} + +uses + fpsUtils, fpsNumFormat, + sCurrencyForm; + +const + CURR_VALUE = 100.0; + +var + PageIndex: Integer = 0; // stores the previously selected page index (to open the form always with previously used page) + + +{ TFormatSettingsForm } + +procedure TFormatSettingsForm.DateTimeFormatChange(Sender: TObject); +var + fs: TFormatSettings; + ctrl: TWinControl; + dt: TDateTime; + s: String; +begin + fs := GetFormatSettings; + dt := FSampleDateTime; + ctrl := ActiveControl; + + if (ctrl = CbLongDateFormat) then + begin + FDateFormatSample := fs.LongDateFormat; + s := FormatDateTime(FDateFormatSample, dt, fs); + LblDateTimeSample.Caption := 'Sample date:'#13 + s; + end + else + if (ctrl = CbShortDateFormat) then + begin + FDateFormatSample := fs.ShortDateFormat; + s := FormatDateTime(FDateFormatSample, dt, fs); + LblDateTimeSample.Caption := 'Sample date:'#13 + s; + end + else + if (ctrl = FCbDateSeparator) then begin + s := FormatDateTime(FDateFormatSample, dt, fs); + LblDateTimeSample.Caption := 'Sample date:'#13 + s; + end + else + if (ctrl = CbLongTimeFormat) then + begin + FTimeFormatSample := fs.LongTimeFormat; + s := FormatDateTime(FTimeFormatSample, dt, fs); + LblDateTimeSample.Caption := 'Sample time:'#13 + s; + end + else + if (ctrl = CbShortTimeFormat) then + begin + FTimeFormatSample := fs.ShortTimeFormat; + s := FormatDateTime(FTimeFormatSample, dt, fs); + LblDateTimeSample.Caption := 'Sample time:'#13 + s; + end + else + if (ctrl = FCbTimeSeparator) then + begin + s := FormatDateTime(FTimeFormatSample, dt, fs); + LblDateTimeSample.Caption := 'Sample time:'#13 + s; + { + end + else + begin + s := AnsiToUTF8(FormatDateTime('c', dt, fs)); + LblDateTimeSample.Caption := 'Sample date/time:'#13 + s; + } + end; + + LblDateTimeSample.Visible := (PageControl.Activepage = PgDateTime) and + ((FDateFormatSample <> '') or (FTimeFormatSample <> '')); +// Application.ProcessMessages; +end; + +procedure TFormatSettingsForm.BtnCurrencyClick(Sender: TObject); +var + F: TCurrencyForm; +begin + F := TCurrencyForm.Create(nil); + try + F.CurrencySymbol := EdCurrencySymbol.Text; + if F.ShowModal = mrOK then + EdCurrencySymbol.Text := F.CurrencySymbol; + finally + F.Free; + end; +end; + +procedure TFormatSettingsForm.EdCurrencySymbolChange(Sender: TObject); +var + currSym: String; +begin + currSym := EdCurrencySymbol.Text; + BuildCurrencyFormatList(CbPosCurrencyFormat.Items, true, CURR_VALUE, currSym); + BuildCurrencyFormatList(CbNegCurrencyFormat.Items, false, CURR_VALUE, currSym); +end; + +procedure TFormatSettingsForm.FormCloseQuery(Sender: TObject; + var CanClose: boolean); +begin + Unused(Sender, CanClose); + PageIndex := PageControl.ActivePageIndex; +end; + +procedure TFormatSettingsForm.FormCreate(Sender: TObject); +const + DROPDOWN_COUNT = 32; +var + w: Integer; +begin + PageControl.ActivePageIndex := PageIndex; + + CbLongDateFormat.DropdownCount := DROPDOWN_COUNT; + CbShortDateFormat.DropdownCount := DROPDOWN_COUNT; + CbLongTimeFormat.DropdownCount := DROPDOWN_COUNT; + CbShortTimeFormat.DropdownCount := DROPDOWN_COUNT; + CbPosCurrencyFormat.DropdownCount := DROPDOWN_COUNT; + CbNegCurrencyFormat.DropdownCount := DROPDOWN_COUNT; + + w := CbLongDateFormat.Width; + FCbDecimalSeparator := TFormatSeparatorCombo.Create(self); + with FCbDecimalSeparator do + begin + Parent := PgNumber; + Left := CbLongDateFormat.Left; + Width := w; + Top := CbLongDateFormat.Top; + TabOrder := 0; + SeparatorKind := skDecimal; + end; + LblDecimalSeparator.FocusControl := FCbDecimalSeparator; + + FCbThousandSeparator := TFormatSeparatorCombo.Create(self); + with FCbThousandSeparator do + begin + Parent := PgNumber; + Left := FCbDecimalSeparator.Left; + Width := w; + Top := FCBDecimalSeparator.Top + 32; + TabOrder := FCbDecimalSeparator.TabOrder + 1; + SeparatorKind := skThousand; + end; + LblThousandSeparator.FocusControl := FCbThousandSeparator; + + FCbDateSeparator := TFormatSeparatorCombo.Create(self); + with FCbDateSeparator do + begin + Parent := PgDateTime; + Left := CbShortDateFormat.Left; + Width := w; + Top := CbShortDateFormat.Top + 32; + TabOrder := CbShortDateFormat.TabOrder + 1; + SeparatorKind := skDate; + OnChange := @DateTimeFormatChange; + OnEnter := @DateTimeFormatChange; + end; + LblDateSeparator.FocusControl := FCbDateSeparator; + + FEdLongMonthNames := TMonthDayNamesEdit.Create(self); + with FEdLongMonthNames do + begin + Parent := PgDateTime; + Left := CbShortDateFormat.Left; + {$IFDEF LCL_FULLVERSION AND LCL_FULLVERSION > 1020600} + Width := w; + {$ELSE} + Width := w - Button.Width; + {$ENDIF} + Top := CbShortDateFormat.Top + 32*2; + OnChange := @DateTimeFormatChange; + OnEnter := @DateTimeFormatChange; + TabOrder := CbShortDateFormat.TabOrder + 2; + end; + LblLongMonthNames.FocusControl := FEdLongMonthNames; + + FEdShortMonthNames := TMonthDayNamesEdit.Create(self); + with FEdShortMonthNames do + begin + Parent := PgDateTime; + Left := CbShortDateFormat.Left; + Width := FEdLongMonthNames.Width; + Top := CbShortDateFormat.Top + 32*3; + TabOrder := CbShortDateFormat.TabOrder + 3; + OnChange := @DateTimeFormatChange; + OnEnter := @DateTimeFormatChange; + end; + LblShortMonthNames.FocusControl := FEdShortMonthNames; + + FEdLongDayNames := TMonthDayNamesEdit.Create(self); + with FEdLongDayNames do + begin + Parent := PgDateTime; + Left := CbShortDateformat.Left; + Width := FEdLongMonthNames.Width; + Top := CbShortDateFormat.Top + 32*4; + TabOrder := CbShortDateFormat.TabOrder + 4; + OnChange := @DateTimeFormatChange; + OnEnter := @DateTimeFormatChange; + end; + LblLongDayNames.FocusControl := FEdLongDayNames; + + FEdShortDayNames := TMonthDayNamesEdit.Create(self); + with FEdShortDayNames do + begin + Parent := PgDateTime; + Left := CbShortDateFormat.Left; + Width := FEdLongMonthNames.Width; + Top := CbShortDateFormat.Top + 32*5; + TabOrder := CbShortDateFormat.TabOrder + 5; + OnChange := @DateTimeFormatChange; + OnEnter := @DateTimeFormatChange; + end; + LblShortDayNames.FocusControl := FEdShortDayNames; + + FCbTimeSeparator := TFormatSeparatorCombo.Create(self); + with FCbTimeSeparator do + begin + Parent := PgDateTime; + Left := CbShortTimeFormat.Left; + Width := w; + Top := CbShortTimeFormat.Top + 32; + TabOrder := CbShortTimeFormat.TabOrder + 1; + SeparatorKind := skTime; + OnChange := @DateTimeFormatChange; + OnEnter := @DateTimeFormatChange; + end; + LblTimeSeparator.FocusControl := FCbTimeSeparator; + + FDateFormatSample := ''; + FTimeFormatSample := ''; + FSampleDateTime := now(); + + LblDateTimeSample.Visible := false; + + // Published property not available in old Laz versions + EdCurrencyDecimals.Alignment := taRightJustify; +end; + +procedure TFormatSettingsForm.OKButtonClick(Sender: TObject); +var + msg: String; + C: TWinControl; + cParent: TWinControl; +begin + if not ValidData(C, msg) then + begin + cParent := C.Parent; + while (cParent <> nil) and not (cParent is TTabSheet) do + cParent := cParent.Parent; + PageControl.ActivePage := cParent as TTabSheet; + if C.CanFocus then C.SetFocus; + MessageDlg(msg, mtError, [mbOK], 0); + ModalResult := mrNone; + end; +end; + +procedure TFormatSettingsForm.PageControlChange(Sender: TObject); +begin + LblDateTimeSample.Visible := (PageControl.Activepage = PgDateTime) and + ((FDateFormatSample <> '') or (FTimeFormatSample <> '')); +end; + +function TFormatSettingsForm.GetFormatSettings: TFormatSettings; +begin + Result := DefaultFormatSettings; + + // --- Number format parameters -- + // Decimal separator + Result.DecimalSeparator := FCbDecimalSeparator.Separator; + // Thousand separator + Result.ThousandSeparator := FCbThousandSeparator.Separator; + + // --- Currency format parameters --- + // Currency symbol + Result.CurrencyString := EdCurrencySymbol.Text; + // Currency decimal places + Result.CurrencyDecimals := EdCurrencyDecimals.Value; + // Positive currency format + Result.CurrencyFormat := CbPosCurrencyFormat.ItemIndex; + // Negative currency format + Result.NegCurrFormat := CbNegCurrencyFormat.ItemIndex; + + // --- Date format parameters --- + // Long date format string + Result.LongDateFormat := CbLongDateFormat.Text; + // Short date format string + Result.ShortDateFormat := CbShortDateFormat.Text; + // Date separator + Result.DateSeparator := FCbDateSeparator.Separator; + // Long month names + FEdLongMonthNames.GetNames(Result.LongMonthNames); + // Short month names + FEdShortMonthNames.GetNames(Result.ShortMonthNames); + // Long day names + FEdLongDayNames.GetNames(Result.LongDayNames); + // Short day names + FEdShortDayNames.GetNames(Result.ShortDayNames); + + // --- Time format parameters --- + // Long time format string + Result.LongTimeFormat := CbLongTimeFormat.Text; + // Short time format string + Result.ShortTimeFormat := CbShortTimeFormat.Text; + // Time separator + Result.TimeSeparator := FCbTimeSeparator.Separator; +end; + +procedure TFormatSettingsForm.SetFormatSettings(const AValue: TFormatSettings); +var + i: Integer; +begin + // --- Number format parameters --- + FCbDecimalSeparator.Separator := AValue.DecimalSeparator; + FCbThousandSeparator.Separator := AValue.ThousandSeparator; + + // --- Currency format parameters --- + // Currency symbol + EdCurrencySymbol.Text := AValue.CurrencyString; + // Currency decimal places + EdCurrencyDecimals.Value := AValue.CurrencyDecimals; + // Positive currency format + CbPosCurrencyFormat.ItemIndex := AValue.CurrencyFormat; + // Negative currency format + CbNegCurrencyFormat.ItemIndex := AValue.NegCurrFormat; + + // --- Date format parameters --- + // Long date format string + i := CbLongDateFormat.Items.IndexOf(AValue.LongDateFormat); + if i = -1 then + CbLongDateFormat.ItemIndex := CbLongDateFormat.Items.Add(AValue.LongDateFormat) + else + CbLongDateFormat.ItemIndex := i; + // Short date format string + i := CbShortDateFormat.Items.IndexOf(AValue.ShortDateFormat); + if i = -1 then + CbShortDateFormat.ItemIndex := CbShortDateFormat.items.Add(AValue.ShortDateFormat) + else + CbShortDateFormat.ItemIndex := i; + // Date separator + FCbDateSeparator.Separator := AValue.DateSeparator; + // Long month names + FEdLongMonthNames.SetNames(AValue.LongMonthNames, 12, false, 'Error'); + // Short month names + FEdShortMonthNames.SetNames(AValue.ShortMonthNames, 12, true, 'Error'); + // Long day names + FEdLongDayNames.SetNames(AValue.LongDayNames, 7, false, 'Error'); + // Short month names + FEdShortDayNames.SetNames(AValue.ShortDayNames, 7, true, 'Error'); + + // --- Time format parameters --- + + // Long time format string + i := CbLongTimeFormat.items.IndexOf(AValue.LongTimeFormat); + if i = -1 then + CbLongTimeFormat.ItemIndex := CbLongTimeFormat.Items.Add(AValue.LongTimeFormat) + else + CbLongTimeFormat.ItemIndex := i; + // Short time format string + i := cbShortTimeFormat.Items.IndexOf(AValue.ShortTimeFormat); + if i = -1 then + CbShortTimeFormat.itemIndex := CbShortTimeFormat.Items.Add(AValue.ShortTimeFormat); + // Time separator + FCbTimeSeparator.Separator := AValue.TimeSeparator; +end; + +function TFormatSettingsForm.ValidData(out AControl: TWinControl; + out AMsg: String): Boolean; +begin + Result := false; + if FCbDecimalSeparator.Separator = FCbThousandSeparator.Separator then + begin + AControl := FCbDecimalSeparator; + AMsg := 'Decimal and thousand separators cannot be the same.'; + exit; + end; + Result := true; +end; + +//initialization +// {$I sformatsettingsform.lrs} + +end. + diff --git a/applications/spready/shyperlinkform.lfm b/applications/spready/shyperlinkform.lfm new file mode 100644 index 000000000..1656fe515 --- /dev/null +++ b/applications/spready/shyperlinkform.lfm @@ -0,0 +1,813 @@ +object HyperlinkForm: THyperlinkForm + Left = 327 + Height = 386 + Top = 259 + Width = 498 + Caption = 'Hyperlink' + ClientHeight = 386 + ClientWidth = 498 + OnCreate = FormCreate + ShowHint = True + LCLVersion = '1.5' + object ButtonPanel1: TButtonPanel + Left = 6 + Height = 34 + Top = 346 + Width = 486 + OKButton.Name = 'OKButton' + OKButton.DefaultCaption = True + OKButton.OnClick = OKButtonClick + HelpButton.Name = 'HelpButton' + HelpButton.DefaultCaption = True + CloseButton.Name = 'CloseButton' + CloseButton.DefaultCaption = True + CancelButton.Name = 'CancelButton' + CancelButton.DefaultCaption = True + TabOrder = 0 + ShowButtons = [pbOK, pbCancel] + end + object Panel2: TPanel + Left = 75 + Height = 340 + Top = 0 + Width = 423 + Align = alClient + BevelOuter = bvNone + ClientHeight = 340 + ClientWidth = 423 + TabOrder = 1 + object Notebook: TNotebook + Left = 4 + Height = 246 + Top = 4 + Width = 415 + PageIndex = 2 + Align = alClient + BorderSpacing.Around = 4 + TabOrder = 0 + TabStop = True + object PgInternal: TPage + object GroupBox2: TGroupBox + Left = 0 + Height = 80 + Top = 0 + Width = 415 + Align = alTop + Caption = 'Target within current workbook' + ClientHeight = 60 + ClientWidth = 411 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 0 + object CbWorksheets: TComboBox + Left = 8 + Height = 23 + Top = 24 + Width = 210 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + OnChange = UpdateHyperlinkInfo + ParentFont = False + Style = csDropDownList + TabOrder = 0 + end + object Label5: TLabel + Left = 8 + Height = 15 + Top = 6 + Width = 59 + Caption = 'Worksheet:' + ParentColor = False + ParentFont = False + end + object Label6: TLabel + Left = 226 + Height = 15 + Top = 8 + Width = 66 + Anchors = [akTop, akRight] + Caption = 'Cell address:' + ParentColor = False + ParentFont = False + end + object CbCellAddress: TComboBox + Left = 226 + Height = 23 + Top = 24 + Width = 176 + Anchors = [akTop, akRight] + ItemHeight = 15 + OnChange = UpdateHyperlinkInfo + OnEditingDone = CbCellAddressEditingDone + ParentFont = False + TabOrder = 1 + end + end + end + object PgFile: TPage + object GbFileName: TGroupBox + Left = 0 + Height = 64 + Top = 0 + Width = 407 + Align = alTop + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 8 + Caption = 'File / Document' + ClientHeight = 44 + ClientWidth = 403 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 0 + object CbFileName: TComboBox + Left = 8 + Height = 23 + Top = 8 + Width = 307 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + OnChange = UpdateHyperlinkInfo + OnEditingDone = CbFileNameEditingDone + ParentFont = False + TabOrder = 0 + end + object BtnBrowseFile: TButton + Left = 320 + Height = 23 + Top = 8 + Width = 75 + Anchors = [akTop, akRight] + Caption = 'Browse...' + OnClick = BtnBrowseFileClick + ParentFont = False + TabOrder = 1 + end + end + object GbFileBookmark: TGroupBox + Left = 0 + Height = 64 + Top = 72 + Width = 407 + Align = alTop + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 8 + Caption = 'Bookmark within document' + ClientHeight = 44 + ClientWidth = 403 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 1 + object CbFileBookmark: TComboBox + Left = 8 + Height = 23 + Top = 8 + Width = 387 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + OnChange = UpdateHyperlinkInfo + OnDropDown = CbFileBookmarkDropDown + ParentFont = False + TabOrder = 0 + end + end + end + object PgInternet: TPage + object GbInternetLinkType: TGroupBox + Left = 0 + Height = 64 + Top = 0 + Width = 407 + Align = alTop + BorderSpacing.Right = 8 + Caption = 'Type of link' + ClientHeight = 44 + ClientWidth = 403 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 0 + object RbHTTP: TRadioButton + Left = 11 + Height = 19 + Top = 7 + Width = 42 + Caption = 'http' + Checked = True + OnChange = HTTP_FTP_Change + ParentFont = False + TabOrder = 1 + TabStop = True + end + object RbFTP: TRadioButton + Left = 77 + Height = 19 + Top = 7 + Width = 35 + Caption = 'ftp' + OnChange = HTTP_FTP_Change + ParentFont = False + TabOrder = 0 + end + end + object InternetNotebook: TNotebook + Left = 0 + Height = 182 + Top = 64 + Width = 415 + PageIndex = 1 + Align = alClient + TabOrder = 1 + TabStop = True + object PgHTTP: TPage + object GbHttp: TGroupBox + Left = 0 + Height = 144 + Top = 8 + Width = 407 + Align = alTop + BorderSpacing.Top = 8 + BorderSpacing.Right = 8 + Caption = 'Bookmark within document' + ClientHeight = 124 + ClientWidth = 403 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 0 + object CbHttpAddress: TComboBox + Left = 8 + Height = 23 + Top = 32 + Width = 384 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + OnEditingDone = CbHttpAddressEditingDone + ParentFont = False + TabOrder = 0 + end + object EdHttpBookmark: TEdit + Left = 8 + Height = 23 + Top = 86 + Width = 384 + ParentFont = False + TabOrder = 1 + end + object LblHttpAddress: TLabel + Left = 8 + Height = 15 + Top = 8 + Width = 121 + Caption = 'URL of web document;' + FocusControl = CbHttpAddress + ParentColor = False + ParentFont = False + end + object LblHttpBookmark: TLabel + Left = 8 + Height = 15 + Top = 64 + Width = 151 + Caption = 'Bookmark within document:' + FocusControl = EdHttpBookmark + ParentColor = False + ParentFont = False + end + end + end + object PfFTP: TPage + object GbFtp: TGroupBox + Left = 0 + Height = 144 + Top = 8 + Width = 407 + Align = alTop + BorderSpacing.Top = 8 + BorderSpacing.Right = 8 + Caption = 'ftp server' + ClientHeight = 124 + ClientWidth = 403 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 0 + object CbFtpServer: TComboBox + Left = 8 + Height = 23 + Top = 32 + Width = 384 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + OnEditingDone = CbFtpServerEditingDone + ParentFont = False + TabOrder = 0 + end + object Label1: TLabel + Left = 8 + Height = 15 + Top = 10 + Width = 35 + Caption = 'Server:' + ParentColor = False + ParentFont = False + end + object LblFtpUserName: TLabel + Left = 8 + Height = 15 + Top = 64 + Width = 59 + Caption = 'User name:' + FocusControl = CbFtpUsername + ParentColor = False + ParentFont = False + end + object CbFtpUsername: TComboBox + Left = 8 + Height = 23 + Top = 86 + Width = 190 + ItemHeight = 15 + ParentFont = False + TabOrder = 1 + end + object LblFtpPassword: TLabel + Left = 208 + Height = 15 + Top = 64 + Width = 53 + Caption = 'Password:' + FocusControl = CbFtpPassword + ParentColor = False + ParentFont = False + end + object CbFtpPassword: TComboBox + Left = 208 + Height = 23 + Top = 86 + Width = 182 + ItemHeight = 15 + ParentFont = False + TabOrder = 2 + end + end + end + end + end + object PgMail: TPage + object GbMailRecipient: TGroupBox + Left = 0 + Height = 60 + Top = 0 + Width = 415 + Align = alTop + BorderSpacing.Bottom = 8 + Caption = 'Mail address of recipient' + ClientHeight = 40 + ClientWidth = 411 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 0 + object CbMailRecipient: TComboBox + Left = 8 + Height = 23 + Top = 6 + Width = 397 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + OnEditingDone = CbMailRecipientEditingDone + ParentFont = False + TabOrder = 0 + end + end + object GroupBox8: TGroupBox + Left = 0 + Height = 60 + Top = 68 + Width = 415 + Align = alTop + BorderSpacing.Bottom = 8 + Caption = 'Subject' + ClientHeight = 40 + ClientWidth = 411 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 1 + object EdMailSubject: TEdit + Left = 8 + Height = 23 + Top = 6 + Width = 397 + Anchors = [akTop, akLeft, akRight] + OnChange = UpdateHyperlinkInfo + ParentFont = False + TabOrder = 0 + end + end + end + end + object HyperlinkInfo: TLabel + Left = 8 + Height = 15 + Top = 321 + Width = 407 + Align = alBottom + BorderSpacing.Left = 8 + BorderSpacing.Top = 8 + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 4 + Caption = 'HyperlinkInfo' + ParentColor = False + WordWrap = True + end + object Bevel1: TBevel + Left = 4 + Height = 3 + Top = 310 + Width = 415 + Align = alBottom + BorderSpacing.Left = 4 + BorderSpacing.Right = 4 + Shape = bsBottomLine + end + object GroupBox6: TGroupBox + Left = 0 + Height = 56 + Top = 254 + Width = 415 + Align = alBottom + BorderSpacing.Right = 8 + Caption = 'Cell tooltip' + ClientHeight = 36 + ClientWidth = 411 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 1 + object EdTooltip: TEdit + Left = 8 + Height = 23 + Top = 3 + Width = 392 + Anchors = [akTop, akLeft, akRight] + ParentFont = False + TabOrder = 0 + Text = 'EdTooltip' + end + end + end + object ToolBar: TToolBar + Left = 4 + Height = 336 + Top = 4 + Width = 67 + Align = alLeft + AutoSize = True + BorderSpacing.Around = 4 + ButtonHeight = 56 + ButtonWidth = 64 + Caption = 'ToolBar' + Color = clWindow + EdgeBorders = [ebLeft, ebTop, ebRight, ebBottom] + EdgeInner = esNone + Images = Images + ParentColor = False + ParentFont = False + ShowCaptions = True + TabOrder = 2 + Wrapable = False + object TbInternal: TToolButton + Left = 2 + Top = 1 + AllowAllUp = True + Caption = 'internal' + Down = True + ImageIndex = 0 + OnClick = ToolButtonClick + end + object TbFile: TToolButton + Tag = 1 + Left = 2 + Top = 57 + AllowAllUp = True + Caption = 'File' + ImageIndex = 1 + OnClick = ToolButtonClick + end + object TbInternet: TToolButton + Tag = 2 + Left = 2 + Top = 113 + AllowAllUp = True + Caption = 'Internet' + ImageIndex = 2 + OnClick = ToolButtonClick + end + object TbMail: TToolButton + Tag = 3 + Left = 2 + Top = 169 + AllowAllUp = True + Caption = 'Mail' + ImageIndex = 3 + OnClick = ToolButtonClick + end + end + object Images: TImageList + Height = 24 + Width = 24 + left = 48 + top = 296 + Bitmap = { + 4C69040000001800000018000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF007E7E54007F7F554D7F7F55667F7F55667F7F + 55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F + 55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F + 55667F7F55667F7F554DFFFFFF007E7E54007E7E5467FFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF7D7D5467FFFFFF007C7C52007C7C5268FFFFFFFFFEFEFEFFFEFE + FEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFE + FEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFE + FEFFFFFFFFFF7B7B5268FFFFFF007A7A51007A7A5168FEFEFDFFFDFDFCFFFFCC + 44FFFECB43FFFECB43FFFDCA42FFFCC941FFFAC73FFFF9C63EFFF8C53DFFF6C3 + 3CFFF5C23AFFF4C139FFF3C038FFF1BE36FFF0BD35FFEFBC34FFEFBC34FFFDFD + FCFFFEFEFDFF79795069FFFFFF0078784F0078784F69FEFEFCFFFCFCFAFFFFCC + 44FFFFEE88FFFEED87FFFDCA42FFFCEB85FFFBEA84FFF9C63EFFF8E781FFF6E5 + 80FFF5C23AFFF4E37DFFF2E17BFFF1BE36FFF0DF79FFEFDE78FFEFBC34FFFCFC + FAFFFEFEFCFF76764E6AFFFFFF0076764D0076764D6AFDFDFAFFFBFBF8FFFFCC + 44FFFFEE88FFFEED87FFFDCA42FFFCEB85FFFBEA84FFF9C63EFFF8E781FFF6E5 + 80FFF5C23AFFF4E37DFFF2E17BFFF1BE36FFF0DF79FFEFDE78FFEFBC34FFFBFB + F8FFFDFDFAFF74744B6BFFFFFF0073734B0073734B6BFDFDF9FFFAFAF6FFFFCC + 44FFFECB43FFFECB43FFF5CE64FFEBD285FFE9D083FFE8CF82FFE7CE81FFE5CC + 80FFE4CB7EFFE3CA7DFFE2C97CFFE0C77AFFDFC679FFDEC578FFDEC578FFFAFA + F6FFFDFDF9FF7171496CFFFFFF00717149007171496CFCFCF8FFF8F8F4FFFFCC + 44FFFFEE88FFFEED87FFECD286FFFCFCFAFFFCFCFAFFD7D7C6FFFCFCFAFFFCFC + FAFFD3D3C2FFFCFCFAFFFCFCFAFFCFCFBEFFFCFCFAFFFCFCFAFFCDCDBCFFF8F8 + F4FFFCFCF8FF6E6E466DFFFFFF006E6E46006E6E466DFBFBF6FFF7F7F1FFFFCC + 44FFFFEE88FFFEED87FFECD286FFFBFBF8FFFBFBF8FFD7D7C6FFFBFBF8FFFBFB + F8FFD3D3C2FFFBFBF8FFFBFBF8FFCFCFBEFFFBFBF8FFFBFBF8FFCDCDBCFFF7F7 + F1FFFBFBF6FF6A6A436EFFFFFF006B6B44006B6B446EFAFAF4FFF5F5EFFFFFCC + 44FFFECB43FFFECB43FFECD286FFDADAC9FFD8D8C7FFDFDFD0FFD6D6C5FFD4D4 + C3FFDCDCCEFFD2D2C1FFD1D1C0FFD9D9CBFFCECEBDFFCDCDBCFFCDCDBCFFF5F5 + EFFFFAFAF4FF67674070FFFFFF00686841006868416FFAFAF2FFF4F4ECFFFFCC + 44FFFFEE88FFFEED87FFECD286FFFAFAF6FFFAFAF6FFD7D7C6FFFAFAF6FFFAFA + F6FFD3D3C2FFFAFAF6FFFAFAF6FFCFCFBEFFFAFAF6FFFAFAF6FFCDCDBCFFF4F4 + ECFFFAFAF2FF63633D71FFFFFF0065653F0065653F70F9F9F0FFF2F2E9FFFFCC + 44FFFFEE88FFFEED87FFECD286FFF9F9F4FFF9F9F4FFD7D7C6FFF9F9F4FFF9F9 + F4FFD3D3C2FFF9F9F4FFF9F9F4FFCFCFBEFFF9F9F4FFF9F9F4FFCDCDBCFFF2F2 + E9FFF9F9F0FF60603A73FFFFFF0062623C0062623C72F8F8EEFFF0F0E6FFFFCC + 44FFFECB43FFFECB43FFECD286FFDADAC9FFD8D8C7FFDDDDCEFFD6D6C5FFD4D4 + C3FFDBDBCCFFD2D2C1FFD1D1C0FFD8D8C9FFCECEBDFFCDCDBCFFCDCDBCFFF0F0 + E6FFF8F8EEFF5C5C3674FFFFFF005F5F39005F5F3973F7F7ECFFEFEFE4FFFFCC + 44FFFFEE88FFFEED87FFECD286FFF7F7F2FFF7F7F2FFD7D7C6FFF7F7F2FFF7F7 + F2FFD3D3C2FFF7F7F2FFF7F7F2FFCFCFBEFFF7F7F2FFF7F7F2FFCDCDBCFFEFEF + E4FFF7F7ECFF58583375FFFFFF005C5C36005C5C3674F6F6EBFFEDEDE1FFFFCC + 44FFFFEE88FFFEED87FFECD286FFF6F6F1FFF6F6F1FFD7D7C6FFF6F6F1FFF6F6 + F1FFD3D3C2FFF6F6F1FFF6F6F1FFCFCFBEFFF6F6F1FFF6F6F1FFCDCDBCFFEDED + E1FFF6F6EBFF55553077FFFFFF005959340059593475F6F6E9FFECECDFFFFFCC + 44FFFECB43FFFECB43FFECD286FFDADAC9FFD8D8C7FFD7D7C6FFD6D6C5FFD4D4 + C3FFD3D3C2FFD2D2C1FFD1D1C0FFCFCFBEFFCECEBDFFCDCDBCFFCDCDBCFFECEC + DFFFF6F6E9FF50502B79FFFFFF005656310056563177F5F5E7FFEAEADDFFEAEA + DDFFEAEADDFFEAEADDFFEAEADDFFEAEADDFFEAEADDFFEAEADDFFEAEADDFFEAEA + DDFFEAEADDFFEAEADDFFEAEADDFFEAEADDFFEAEADDFFEAEADDFFEAEADDFFEAEA + DDFFF5F5E7FF42421F7FFFFFFF0052522E0052522E78F4F4E6FFE9E9DBFFE9E9 + DBFFE9E9DBFFE9E9DBFFEFEFE0FFF4F4E6FFF4F4E6FFF4F4E6FFF4F4E6FFF4F4 + E6FFF4F4E6FFF4F4E6FFF4F4E6FFF4F4E6FFF4F4E6FFF4F4E6FFF4F4E6FFF4F4 + E6FFFAFAEBFF34341384FFFFFF00494925004949257CF4F4E5FFE8E8D9FFE8E8 + D9FFE8E8D9FFE8E8D9FFF4F4E5FFAAAA99FFAAAA99FFAAAA99FFAAAA99FFAAAA + 99FFAAAA99FFAAAA99FF29290988292909882929098829290988292909882929 + 0988292909882A2A0A66FFFFFF003C3C1A003C3C1A80F5F5E5FFE7E7D7FFE7E7 + D7FFE7E7D7FFE7E7D7FFF5F5E5FF67674FC5F5F5E5FFE7E7D7FFE7E7D7FFE7E7 + D7FFE7E7D7FFF5F5E5FF2323048A262607002727070027270700272707002727 + 07002727070029290900FFFFFF000D0D050031311174D4D4C0DCF4F4E3FFF3F3 + E2FFF3F3E2FFF4F4E3FFD4D4C0DC2323048AD0D0BDDEF4F4E3FFF3F3E2FFF3F3 + E2FFF4F4E3FFD0D0BDDE23230479090901000000000000000000000000000000 + 00000000000000000000FFFFFF0000000011171705402727097B282809882828 + 098828280988282809882727097B1A1A035F2222047C2323048A2323048A2323 + 048A2323048A2222047C1212024C0000002F000000280000001F000000160000 + 000D0000000600000001FFFFFF000000000000000012000000190000001A0000 + 001A0000001A0000001A0000001A0000001A0000001A0000001A0000001A0000 + 001A0000001A0000001A0000001A0000001800000014000000100000000B0000 + 00070000000300000001FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000088CB000088CB000088 + CC410088CC810088CC810088CC810088CC810088CC810088CC810088CC810088 + CC810088CC810088CC810088CC810088CC810088CC810088CC810088CC610088 + CB000088CB00FFFFFF00FFFFFF00FFFFFF00FFFFFF000087CB000087CB000087 + CB826FCCECE092E1F7FFADF1FFFFAEF2FFFFAEF2FFFFAEF2FFFFAEF2FFFFAEF2 + FFFFAEF2FFFFAEF2FFFFAEF2FFFFAEF2FFFFAEF2FFFFB1F5FFFF0087CB820087 + CB000087CB00FFFFFF00FFFFFF00FFFFFF00FFFFFF000086C9000086C9000086 + C983B0F5FFFF91E1F6FF5DC0E7FF72CCEEFF8CDCF6FFA6ECFEFFA8EDFEFFA8ED + FEFFA8EDFEFFA8EDFEFFA8EDFEFFA8EDFEFFA8EDFEFFADF2FFFF0086C9830086 + C9000086C900FFFFFF00FFFFFF00FFFFFF00FFFFFF000085C8000085C8000085 + C885ADF1FFFFABEFFEFFACF1FEFF8FDFF5FF69C7EAFF59BCE6FF76C9E6FFA6EB + FDFFA6EBFDFFA6EBFDFFA6EBFDFFA6EBFDFFA6EBFDFFABF0FEFF0085C8850085 + C8000085C800FFFFFF00FFFFFF00FFFFFF00FFFFFF000084C6000084C6000084 + C687ABEFFEFFA6EAFDFFA6EAFDFFA9EEFDFFADF1FEFFA1EAFAFF4FAFD8FF9BDC + EEFFA2E6F9FFA4E9FCFFA4E9FCFFA4E9FCFFA4E9FCFFA9EEFDFF0084C6870084 + C6000084C600FFFFFF00FFFFFF00FFFFFF00FFFFFF000083C4000083C4000083 + C489A8EEFDFFA3E9FCFFA3E9FCFFA3E9FCFFA3E9FCFFADF2FEFF49AEDAFF91CF + E1FF91CFE1FF97D8EBFF9FE4F7FFA1E6FAFFA1E6FAFFA6EBFCFF0083C4890083 + C4000083C400FFFFFF00FFFFFF00FFFFFF00FFFFFF000081C2000081C2000081 + C28BA6ECFCFFA1E7FBFFA1E7FBFFA1E7FBFFA1E7FBFFABF0FDFF41A5D2FF8ECD + E0FF8ECDE0FF8ECDE0FF96D9EDFF9EE4F9FF9EE4F9FFA4E9FBFF0081C28B0081 + C2000081C200FFFFFF00FFFFFF00FFFFFF00FFFFFF000080C0000080C0000080 + C08DA4E9FBFF9EE4F9FF9EE4F9FF9EE4F9FF9EE4F9FFA9EEFCFF3A9BC7FF8ACA + DEFF8ACADEFF8ACADEFF92D6EBFF9AE1F7FF9AE1F7FFA0E6F9FF0080C08D0080 + C0000080C000FFFFFF00FFFFFF00FFFFFF00FFFFFF00007EBD00007EBD00007E + BD8FA1E7FAFF9BE2F8FF9BE2F8FF9BE2F8FF9BE2F8FFA7ECFCFF3696C2FF88C7 + DDFF88C7DDFF88C7DDFF90D3EAFF97DEF6FF97DEF6FF9DE4F9FF007EBD8F007E + BD00007DBB00FFFFFF00FFFFFF00FFFFFF00FFFFFF00007DBB00007DBB00007D + BB919EE5F9FF98DFF6FF98DFF6FF98DFF6FF98DFF6FFA4EAFBFF3393BFFF84C5 + DBFF84C5DBFF84C5DBFF8CD0E8FF93DBF4FF93DBF4FF9AE1F7FF007DBB91007D + BB33007BB800FFFFFF00FFFFFF00FFFFFF00FFFFFF00007BB800007BB800007B + B8949CE3F8FF95DDF5FF95DDF5FF95DDF5FF95DDF5FFA2E8FAFF318FBCFF81C2 + D9FF81C2D9FF81C2D9FF89CDE6FF90D8F2FF90D8F2FF90D8F2FF90D8F2FF007B + B894007BB834FFFFFF00FFFFFF00FFFFFF00FFFFFF000079B6000079B6000079 + B69699E0F6FF92DAF3FF92DAF3FF92DAF3FF92DAF3FF9FE5F9FF2E8CB8FF7EBF + D8FF7EBFD8FF7EBFD8FF85CAE4FF8CD5F0FF8CD5F0FF8CD5F0FFFEFEFDFF8CD5 + F0FF0079B696FFFFFF00FFFFFF00FFFFFF00FFFFFF000077B3000077B3000077 + B39996DEF6FF8FD8F2FF8FD8F2FF8FD8F2FF8FD8F2FF9CE3F9FF2B88B5FF7BBD + D6FF7BBDD6FF7BBDD6FF82C8E2FF89D2EEFF89D2EEFF89D2EEFFF8F8F3FF89D2 + EEFF0077B399FFFFFF00FFFFFF00FFFFFF00FFFFFF000076B0000076B0000076 + B09B93DBF4FF8CD5F0FF8CD5F0FF8CD5F0FF8CD5F0FF9AE0F8FF2986B2FF78BA + D5FF78BAD5FF78BAD5FF7FC5E1FF85CFEDFF85CFEDFF85CFEDFFF0F0E6FF85CF + EDFF0076B09BFFFFFF00FFFFFF00FFFFFF00FFFFFF000074AE000074AE000074 + AE9E90D8F3FF89D2EEFF89D2EEFF89D2EEFF89D2EEFF97DEF7FF2682AFFF75B8 + D3FF75B8D3FF75B8D3FF7CC3DFFF82CDEBFF82CDEBFF82CDEBFFE9E9DBFF82CD + EBFF0074AE9EFFFFFF00FFFFFF00FFFFFF00FFFFFF000072AB000072AB000072 + ABA08ED6F2FF86D0EDFF86D0EDFF86D0EDFF86D0EDFF95DCF6FF257FACFF72B5 + D2FF72B5D2FF72B5D2FF79C0DEFF7FCAEAFF7FCAEAFF7FCAEAFFFEC941FF7FCA + EAFF0072ABA0FFFFFF00FFFFFF00FFFFFF00FFFFFF00006EA600006EA600006E + A6A58BD4F0FF83CEEBFF83CEEBFF83CEEBFF83CEEBFF93DAF5FF237DA9FF70B4 + D0FF70B4D0FF70B4D0FF77BEDCFF7DC8E8FF7DC8E8FF7DC8E8FFF4B62EFF7DC8 + E8FF006EA6A5FFFFFF00FFFFFF00FFFFFF00FFFFFF00001B280000679B000067 + 9BAF89D2F0FF81CBEAFF81CBEAFF81CBEAFF81CBEAFF91D8F5FF217AA6FF6EB2 + CFFF6EB2CFFF6EB2CFFF75BCDBFF7BC6E7FF7BC6E7FF7BC6E7FF7BC6E7FF0067 + 9BAF00689D3DFFFFFF00FFFFFF00FFFFFF00FFFFFF0000000000001925000061 + 91B887D0EFFF7EC9E9FF7EC9E9FF7EC9E9FF7EC9E9FF8ED6F4FF227AA5FF74B6 + D4FF74B6D4FF74B6D4FF7BC1E1FF81CBECFF81CBECFF81CBECFF006191B80049 + 6E41001A2600FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000011000000260045 + 689C3590BCF269B8DCFA82CCECFF7CC7E8FF7CC7E8FF8CD4F4FF005C8BEF004F + 77C6004F77C6004F77C6005885C2005B8AC0005B8AC0005B8AC00045689C0000 + 002300000010FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000009000000130000 + 001A005C8A5B0062939F368FBAD16BBADEED80CAEBFF8BD3F3FF005884C70000 + 0031000000310000001F0000001A0000001A0000001A0000001A0000001A0000 + 001200000008FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000000000000000000 + 0000005D8C0000649700006191530060909E1B76A3C551A2CAE2005A88C20000 + 001A000000070000000000000000000000000000000000000000000000000000 + 000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000000000000000000 + 0000005D8C000064970000609000005E8E00005C8A31005B897E005986930000 + 0007000000000000000000000000000000000000000000000000000000000000 + 000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CF7A0200CF7A0200CF7A0200D47E + 0200DC830300E2880300E58A0313E68B034EE78B0388E78B03A6E78B03B8E78B + 03B8E78B03A6E78B0388E68B034EE58A0313E2880300DC830300D47E0200CF7A + 0200CF7A0200CF7A0200FFFFFF00FFFFFF00CF7A0200CF7A0200CF7A0200D47E + 0200DC83030DE0870363E38F13B5EDB459D5F7DCA4EBFBECC5F7FCF3D3FDFCF4 + D4FDFCEEC7F7F7DCA4EBEDB459D5E38F13B5E0870363DC83030DD47E0200CF7A + 0200CF7A0200CF7A0200FFFFFF00FFFFFF00CF7A0200CF7A0200CF7A0200D47E + 021CD780039DE1A146D7EBC68CF7E9C48EFFEAC792FFF0D19EFFF2D4A2FFEFD5 + A8FFFFFAD7FFFFFAD4FFFFFAD4FFFBEDC2F7E8B25BD7D780039DD47E021CCF7A + 0200CF7A0200CF7A0200FFFFFF00FFFFFF00C3710200C5730200CB77021CCF7E + 0CAEE7BD78E5EDCC90FFEBC788FFF7E7BBFFF9EDC5FFF1D29FFFF8DBA5FFF2D7 + A8FFFCF4D2FFFFFAD6FFFFF9D1FFFFF8CBFFFFF9CDFFEDC986E5CF7E0CAECB77 + 021CC5730200C3710200FFFFFF00FFFFFF00B6680200BA6B020DC070039FE8C3 + 82E5E1B570FFE0AD5FFFF1D9A2FFFFF7CCFFFFF7D0FFF5E0B2FFF1D199FFEED1 + A0FFEDD4AAFFFFF7D0FFFFF7CCFFFFF6C6FFFFF5BFFFFFF5C1FFE8C382E5C070 + 039FBA6B020DB6680200FFFFFF00FFFFFF00B0640200B3660266D19C50D9E2BA + 7AFFE6BE76FFE1B771FFFAE6AFFFFFF0BFFFF7E2B2FFE9C487FFE6BE81FFFDEE + C4FFFAEABEFFFAE7B9FFFFEFBDFFFFEFB9FFFFEDB4FFFFECAFFFFFEEB7FFD29E + 52D9B3660266B0640200FFFFFF00FFFFFF00A75D0114AE670EBCD7A866F8D498 + 3AFFE8BD6EFFD49F52FFFCE0A2FFF1D194FFDAA85EFFE5B86AFFDEB16DFFFFEA + B5FFFFE9B4FFE0B87BFFD4A25CFFF9DD9FFFFFE5A4FFFFE4A1FFFADB98FFD09E + 5DF8AB630ABCA75D0114FFFFFF00FFFFFF009B530153BB833DDBCB903DFFD599 + 38FFD79C3AFFD49A3EFFE3B364FFD59F4AFFDDA84FFFDEAB53FFD7A457FFFDDC + 9BFFE9BF7CFFE1B266FFCD9441FFEDC27AFFFFDA92FFF0C67DFFFFD98FFFE1B0 + 66FFB4782EDB9B530153FFFFFF00FFFFFF00914D0190C79355EFE9B160FFDA9F + 47FFD39633FFD59934FFD49836FFD59B39FFD89D3CFFD89E3EFFD1973CFFD79F + 4BFFC98D38FFC58731FFCF9344FFFFCF82FFFFCF80FFD29547FFCE913FFFE2AA + 56FFC48E46EF914D0190FFFFFF00FFFFFF00894700B2F2C07AF8F7BB67FFD797 + 41FFCC8C2AFFD0922DFFD1922DFFD1932EFFD19430FFD19430FFD19430FFCB8C + 2EFFDFA24EFFFFC571FFFFC470FFFCC16DFFDC9E4DFFFFC46FFFC48325FFCB8B + 29FFCD9848F8894700B2FFFFFF00FFFFFF00834200C6D89C54FEC6802CFFE19B + 44FFCE8A2DFFCD8A26FFCE8C26FFCE8C27FFCE8C27FFCE8C27FFCE8C27FFCB88 + 2AFFEDA951FFF2AD57FFFFBB62FFEEA852FFBC7720FFC17E20FFC58222FFCA88 + 24FFD39943FE834200C6FFFFFF00FFFFFF00804000C7C6873DFEC37C21FFE89D + 41FFCB8327FFCB8722FFCC8822FFCC8822FFCC8822FFCC8822FFCC8822FFC985 + 22FFC98224FFBD751EFFE2973FFFFFB354FFC88026FFC57F22FFE79C40FFC67E + 26FFC98C39FE804000C7FFFFFF00FFFFFF00814000B3E59F4FF8C47D1EFFC882 + 20FFCB8521FFCE8822FFCE8823FFCE8823FFCE8823FFCE8924FFCE8924FFCE89 + 24FFCC8623FFC17A1FFFF4A344FFFFAD4BFFC47A22FFCB7F27FFFFAD4AFFFBAA + 48FFD99546F8814000B3FFFFFF00FFFFFF0083420092BF7B32F0CB8220FFD088 + 22FFD08823FFD08823FFD18924FFD18A25FFD18A26FFD18A26FFD18B26FFD18B + 26FFCF8725FFD6892DFFFFAB47FFEE9C3DFFBB701BFFF39F3EFFFFAA45FFFFAA + 45FFDC9544F083420092FFFFFF00FFFFFF0088450054A36018DED48A28FFD488 + 23FFD48924FFD58A25FFD58B27FFD68C29FFD68E2CFFD78E2EFFD78F2FFFD78F + 2FFFD68D2DFFD2882AFFC77C23FFCC7F25FFDA8A2FFFFFAC46FFFFAB46FFFFAE + 4AFFB57024DE88450054FFFFFF00FFFFFF008F4A0014944E04C1D3882DF9DA89 + 24FFDA8A26FFDB8C29FFDC8E2DFFDC9132FFDD9337FFDE953AFFDE963CFFDE96 + 3CFFDE953AFFDD9337FFDC9032FFD28329FFF0A242FFFFB14AFFFFB049FFF3AA + 4CF9975107C18F4A0014FFFFFF00FFFFFF00954E0000974F006AB56A16DFE18D + 2BFFE18C28FFE28F2EFFE39336FFE4973FFFE59C46FFE69F4CFFE6A04FFFE6A0 + 4FFFE69F4CFFE59C46FFE4973FFFD98932FFF0A84BFFFFB954FFFFBA56FFC07A + 26DF974F006A954E0000FFFFFF00FFFFFF00995000009B52000E9F5500A7CC7A + 20EAE78F2FFFE89235FFEA9840FFEB9F4DFFECA558FFEDA960FFEDAC64FFEDAC + 64FFEDA960FFECA558FFEB9F4DFFE0903DFFF1B057FFFFC362FFDA983EEA9F55 + 00A79B52000E99500000FFFFFF00FFFFFF00A2560000A3570000A75A001DAB5D + 03B7D27E22EAEE973DFFEF9D49FFF0A558FFF1AD66FFF2B16EFFF2B473FFF2B4 + 73FFF2B16EFFF1AD66FFF0A558FFE69446FFF3BA66FFDEA145EAAC6005B7A75A + 001DA3570000A2560000FFFFFF00FFFFFF00552E0000552E0000552E0000AE5E + 001DB06000A7CB771ADFEC9A46F8F5A95EFFF5AF6AFFF6B474FFF6B779FFF6B7 + 79FFF6B474FFF5AF6AFFF5A95EFFE59244F8CA822ADFB06000A7AE5E001D552E + 0000552E0000552E0000FFFFFF00FFFFFF000000000000000000000000010000 + 00022E1900119A55006EBB6906C2CF7E23DEE6994BF0F0A963F8F7B271FEF7B2 + 71FEF0A963F8E6994BF0CF7E23DEBA6806C29C56006D2E190011000000020000 + 00010000000000000000FFFFFF00FFFFFF000000000000000000000000030000 + 000C0000001A00000024371F00376E3D006DAB5F009CB96600B5BC6800C7BC68 + 00C7B96600B5AB5F009C6E3D006D371F003700000024000000190000000C0000 + 00020000000000000000FFFFFF00FFFFFF000000000000000000000000020000 + 000800000011000000180000001A0000001A0000001A0000001A0000001A0000 + 001A0000001A0000001A0000001A0000001A0000001800000011000000080000 + 00010000000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF007E7E54007F7F554D7F7F55667F7F55667F7F + 55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F + 55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F + 55667F7F55667F7F554D7E7E54007D7D53007D7D5367E0E0CFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFE0E0CFFF7D7D53677D7D53007A7A51007A7A5168F5F5F0FFDBDBCAFFFEFE + FDFFFEFEFDFFFEFEFDFFFEFEFDFFFEFEFDFFFEFEFDFFFEFEFDFFFEFEFDFFFEFE + FDFFFEFEFDFFFEFEFDFFFEFEFDFFFEFEFDFFFEFEFDFFFEFEFDFFFEFEFDFFDBDB + CAFFF5F5F0FF7A7A51687A7A510077774E0077774E69FDFDFAFFEEEEE5FFD5D5 + C4FFFCFCFAFFFCFCFAFFFCFCFAFFFCFCFAFFFCFCFAFFFCFCFAFFFCFCFAFFFCFC + FAFFFCFCFAFFFCFCFAFFFCFCFAFFFCFCFAFFFCFCFAFFFCFCFAFFD5D5C4FFEEEE + E5FFFDFDFAFF77774E6977774E0074744C0074744C6BFDFDFAFFF8F8F3FFE6E6 + DAFFCFCFBEFFFBFBF7FFFBFBF7FFFBFBF7FFFBFBF7FFFBFBF7FFFBFBF7FFFBFB + F7FFFBFBF7FFFBFBF7FFFBFBF7FFFBFBF7FFFBFBF7FFCFCFBEFFE6E6DAFFF8F8 + F3FFFDFDFAFF74744C6B74744C00717148007171486CFCFCF8FFF9F9F4FFF4F4 + EEFFDEDED0FFC9C9B8FFF9F9F4FFF9F9F4FFF9F9F4FFF9F9F4FFF9F9F4FFF9F9 + F4FFF9F9F4FFF9F9F4FFF9F9F4FFF9F9F4FFC9C9B8FFDEDED0FFF4F4EEFFF9F9 + F4FFFCFCF8FF7171486C717148006D6D45006D6D456DFBFBF5FFF6F6F0FFF6F6 + F0FFF1F1E8FFD9D9C9FFC4C4B3FFF6F6F0FFF6F6F0FFF6F6F0FFF6F6F0FFF6F6 + F0FFF6F6F0FFF6F6F0FFF6F6F0FFC4C4B3FFD9D9C9FFF1F1E8FFF6F6F0FFF6F6 + F0FFFBFBF5FF6D6D456D6D6D4500696942006969426FFAFAF2FFF4F4ECFFF4F4 + ECFFF4F4ECFFEEEEE4FFD6D6C5FFBEBEADFFF4F4ECFFF4F4ECFFF4F4ECFFF4F4 + ECFFF4F4ECFFF4F4ECFFBEBEADFFD6D6C5FFEEEEE4FFF4F4ECFFF4F4ECFFF4F4 + ECFFFAFAF2FF6969426F6969420065653E0065653E71F9F9F0FFF2F2E9FFF2F2 + E9FFF2F2E9FFF2F2E9FFE8E8DBFFD5D5C4FFB9B9A8FFF2F2E9FFF2F2E9FFF2F2 + E9FFF2F2E9FFB9B9A8FFD5D5C4FFE8E8DBFFF2F2E9FFF2F2E9FFF2F2E9FFF2F2 + E9FFF9F9F0FF65653E7165653E0061613A0061613A72F8F8EDFFF0F0E5FFF0F0 + E5FFF0F0E5FFEBEBDFFFDBDBCAFFECECE0FFD7D7C8FFB3B3A2FFF0F0E5FFF0F0 + E5FFB3B3A2FFD7D7C8FFECECE0FFDBDBCAFFEBEBDFFFF0F0E5FFF0F0E5FFF0F0 + E5FFF8F8EDFF61613A7261613A005C5C37005C5C3774F6F6EBFFEDEDE1FFEDED + E1FFE8E8DBFFD8D8C7FFEDEDE1FFEDEDE1FFEBEBDEFFD8D8C9FFAEAE9DFFAEAE + 9DFFD8D8C9FFEBEBDEFFEDEDE1FFEDEDE1FFD8D8C7FFE8E8DBFFEDEDE1FFEDED + E1FFF6F6EBFF5C5C37745C5C37005858330058583376F5F5E8FFEBEBDEFFE5E5 + D7FFD5D5C4FFEBEBDEFFEBEBDEFFEBEBDEFFEBEBDEFFEAEADDFFD9D9CAFFD9D9 + CAFFEAEADDFFEBEBDEFFEBEBDEFFEBEBDEFFEBEBDEFFD5D5C4FFE5E5D7FFEBEB + DEFFF5F5E8FF585833765858330054542F0054542F77F4F4E6FFE3E3D5FFD3D3 + C2FFE9E9DBFFE9E9DBFFE9E9DBFFE9E9DBFFE9E9DBFFE9E9DBFFE9E9DBFFE9E9 + DBFFE9E9DBFFE9E9DBFFE9E9DBFFE9E9DBFFE9E9DBFFE9E9DBFFD3D3C2FFE3E3 + D5FFF4F4E6FF54542F7754542F00494926004949267BEEEEDEFFD0D0BFFFE8E8 + D8FFE8E8D8FFE8E8D8FFE8E8D8FFE8E8D8FFE8E8D8FFE8E8D8FFE8E8D8FFE8E8 + D8FFE8E8D8FFE8E8D8FFE8E8D8FFE8E8D8FFE8E8D8FFE8E8D8FFE8E8D8FFD0D0 + BFFFEEEEDEFF4949267B494926000F0F070038381782CECEBDFFF3F3E2FFF3F3 + E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3 + E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3 + E2FFCECEBDFF383817820F0F0700000000102121096C2A2A0B872A2A0B872A2A + 0B872A2A0B872A2A0B872A2A0B872A2A0B872A2A0B872A2A0B872A2A0B872A2A + 0B872A2A0B872A2A0B872A2A0B872A2A0B872A2A0B872A2A0B872A2A0B872A2A + 0B872A2A0B872121096B0000000E0000000800000011000000190000001A0000 + 001A0000001A0000001A0000001A0000001A0000001A0000001A0000001A0000 + 001A0000001A0000001A0000001A0000001A0000001A0000001A0000001A0000 + 001A000000170000000E00000007FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00 + } + end + object OpenDialog: TOpenDialog + Filter = 'All files (*.*)|*.*' + left = 128 + top = 296 + end +end diff --git a/applications/spready/shyperlinkform.pas b/applications/spready/shyperlinkform.pas new file mode 100644 index 000000000..30ca3fd62 --- /dev/null +++ b/applications/spready/shyperlinkform.pas @@ -0,0 +1,550 @@ +unit sHyperlinkForm; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ButtonPanel, + ExtCtrls, Buttons, StdCtrls, ComCtrls, + fpsTypes, fpspreadsheet; + +type + + { THyperlinkForm } + + THyperlinkForm = class(TForm) + Bevel1: TBevel; + BtnBrowseFile: TButton; + ButtonPanel1: TButtonPanel; + CbFtpServer: TComboBox; + CbFtpUsername: TComboBox; + CbFtpPassword: TComboBox; + CbHttpAddress: TComboBox; + CbFileBookmark: TComboBox; + CbWorksheets: TComboBox; + CbCellAddress: TComboBox; + CbFileName: TComboBox; + CbMailRecipient: TComboBox; + EdHttpBookmark: TEdit; + EdTooltip: TEdit; + EdMailSubject: TEdit; + GroupBox2: TGroupBox; + GbFileName: TGroupBox; + GbInternetLinkType: TGroupBox; + GbHttp: TGroupBox; + GbMailRecipient: TGroupBox; + GroupBox6: TGroupBox; + GbFileBookmark: TGroupBox; + GroupBox8: TGroupBox; + GbFtp: TGroupBox; + Images: TImageList; + HyperlinkInfo: TLabel; + Label1: TLabel; + LblFtpUserName: TLabel; + LblFtpPassword: TLabel; + LblHttpAddress: TLabel; + Label5: TLabel; + Label6: TLabel; + LblHttpBookmark: TLabel; + Notebook: TNotebook; + InternetNotebook: TNotebook; + OpenDialog: TOpenDialog; + PgHTTP: TPage; + PfFTP: TPage; + PgInternal: TPage; + PgFile: TPage; + PgInternet: TPage; + PgMail: TPage; + Panel2: TPanel; + RbFTP: TRadioButton; + RbHTTP: TRadioButton; + ToolBar: TToolBar; + TbInternal: TToolButton; + TbFile: TToolButton; + TbInternet: TToolButton; + TbMail: TToolButton; + procedure BtnBrowseFileClick(Sender: TObject); + procedure CbCellAddressEditingDone(Sender: TObject); + procedure CbFileBookmarkDropDown(Sender: TObject); + procedure CbFileNameEditingDone(Sender: TObject); + procedure CbFtpServerEditingDone(Sender: TObject); + procedure CbHttpAddressEditingDone(Sender: TObject); + procedure CbMailRecipientEditingDone(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure OKButtonClick(Sender: TObject); + procedure HTTP_FTP_Change(Sender: TObject); + procedure ToolButtonClick(Sender: TObject); + procedure UpdateHyperlinkInfo(Sender: TObject); + private + { private declarations } + FWorkbook: TsWorkbook; + FWorksheet: TsWorksheet; + function GetHyperlinkTarget: String; + function GetHyperlinkTooltip: String; + procedure SetHyperlinkKind(AValue: Integer); + procedure SetHyperlinkTarget(const AValue: String); + procedure SetHyperlinkTooltip(const AValue: String); + procedure SetInternetLinkKind(AValue: Integer); + procedure SetWorksheet(AWorksheet: TsWorksheet); + protected + function GetHyperlinkKind: Integer; + function ValidData(out AControl: TWinControl; out AMsg: String): Boolean; + public + { public declarations } + procedure GetHyperlink(out AHyperlink: TsHyperlink); + procedure SetHyperlink(AWorksheet: TsWorksheet; const AHyperlink: TsHyperlink); + end; + +var + HyperlinkForm: THyperlinkForm; + +implementation + +{$R *.lfm} + +uses + URIParser, LazFileUtils, + fpsUtils; + +const + TAG_INTERNAL = 0; + TAG_FILE = 1; + TAG_INTERNET = 2; + TAG_MAIL = 3; + + TAG_HTTP = 0; + TAG_FTP = 1; + +{ THyperlinkForm } + +procedure THyperlinkForm.BtnBrowseFileClick(Sender: TObject); +begin + with OpenDialog do begin + Filename := CbFileName.Text; + if Execute then begin + InitialDir := ExtractFileDir(FileName); + CbFileName.Text := FileName; + if (CbFileName.Text <> '') and (CbFileName.Items.IndexOf(FileName) = -1) then + CbFilename.Items.Insert(0, FileName); + end; + end; +end; + +procedure THyperlinkForm.CbCellAddressEditingDone(Sender: TObject); +begin + CbCellAddress.Text := Uppercase(CbCellAddress.Text); +end; + +procedure THyperlinkForm.CbFileBookmarkDropDown(Sender: TObject); +var + ext: String; + wb: TsWorkbook; + ws: TsWorksheet; + i: Integer; +begin + CbFileBookmark.Items.Clear; + if FileExists(CbFilename.Text) then begin + ext := Lowercase(ExtractFileExt(CbFileName.Text)); + if (ext = '.xls') or (ext = '.xlsx') or (ext = '.ods') then begin + wb := TsWorkbook.Create; + try + wb.ReadFromFile(CbFileName.Text); + for i:=0 to wb.GetWorksheetCount-1 do + begin + ws := wb.GetWorksheetByIndex(i); + CbFileBookmark.Items.Add(ws.Name); + end; + finally + wb.Free; + end; + end; + end; +end; + +procedure THyperlinkForm.CbFileNameEditingDone(Sender: TObject); +begin + if (CbFilename.Text <> '') and + (CbFilename.Items.IndexOf(CbFilename.Text) = -1) + then + CbFileName.Items.Insert(0, CbFileName.Text); +end; + +procedure THyperlinkForm.CbFtpServerEditingDone(Sender: TObject); +begin + if (CbFtpServer.Text <> '') and + (CbFtpServer.Items.IndexOf(CbFtpServer.Text) = -1) + then + CbFtpServer.Items.Insert(0, CbFtpServer.Text); +end; + +procedure THyperlinkForm.CbHttpAddressEditingDone(Sender: TObject); +begin + if (CbHttpAddress.Text <> '') and + (CbHttpAddress.Items.Indexof(CbHttpAddress.Text) = -1) + then + CbHttpAddress.Items.Insert(0, CbHttpAddress.Text); +end; + +procedure THyperlinkForm.CbMailRecipientEditingDone(Sender: TObject); +begin + if (CbMailRecipient.Text <> '') and + (CbMaiLRecipient.Items.IndexOf(CbMailRecipient.Text) = -1) + then + CbMailRecipient.Items.Insert(0, CbMailRecipient.Text); +end; + +procedure THyperlinkForm.FormCreate(Sender: TObject); +begin + HTTP_FTP_Change(nil); +end; + +procedure THyperlinkForm.GetHyperlink(out AHyperlink: TsHyperlink); +begin + AHyperlink.Target := GetHyperlinkTarget; + AHyperlink.Tooltip := GetHyperlinkTooltip; +end; + +function THyperlinkForm.GetHyperlinkKind: Integer; +begin + for Result := 0 to Toolbar.ButtonCount-1 do + if Toolbar.Buttons[Result].Down then + exit; + Result := -1; +end; + +function THyperlinkForm.GetHyperlinkTarget: String; +begin + Result := ''; + case GetHyperlinkKind of + TAG_INTERNAL: + begin //internal + if (CbWorksheets.ItemIndex > 0) and (CbCellAddress.Text <> '') then + Result := '#' + CbWorksheets.Text + '!' + Uppercase(CbCellAddress.Text) + else if (CbWorksheets.ItemIndex > 0) then + Result := '#' + CbWorksheets.Text + '!' + else if (CbCellAddress.Text <> '') then + Result := '#' + Uppercase(CbCellAddress.Text); + end; + + TAG_FILE: + begin // File + if FileNameIsAbsolute(CbFilename.Text) then + Result := FilenameToURI(CbFilename.Text) + else + Result := CbFilename.Text; + if CbFileBookmark.Text <> '' then + Result := Result + '#' + CbFileBookmark.Text; + end; + + TAG_INTERNET: + begin // Internet link + if RbHttp.Checked and (CbHttpAddress.Text <> '') then + begin + if pos('http', Lowercase(CbHttpAddress.Text)) = 1 then + Result := CbHttpAddress.Text + else + Result := 'http://' + CbHttpAddress.Text; + if EdHttpBookmark.Text <> '' then + Result := Result + '#' + EdHttpBookmark.Text; + end else + if RbFtp.Checked and (CbFtpServer.Text <> '') then + begin + if (CbFtpUsername.Text <> '') and (CbFtpPassword.Text <> '') then + Result := Format('ftp://%s:%s@%s', [CbFtpUsername.Text, CbFtpPassword.Text, CbFtpServer.Text]) + else + if (CbFtpUsername.Text <> '') and (CbFtpPassword.Text = '') then + Result := Format('ftp://%s@%s', [CbFtpUsername.Text , CbFtpServer.Text]) + else + Result := 'ftp://anonymous@' + CbFtpServer.Text; + end; + end; + + TAG_MAIL: + begin // Mail + if EdMailSubject.Text <> '' then + Result := Format('mailto:%s?subject=%s', [CbMailRecipient.Text, EdMailSubject.Text]) + else + Result := Format('mailto:%s', [CbMailRecipient.Text]); + end; + end; +end; + +function THyperlinkForm.GetHyperlinkTooltip: String; +begin + Result := EdTooltip.Text; +end; + +procedure THyperlinkForm.OKButtonClick(Sender: TObject); +var + C: TWinControl; + msg: String; +begin + if not ValidData(C, msg) then begin + C.SetFocus; + MessageDlg(msg, mtError, [mbOK], 0); + ModalResult := mrNone; + end; +end; + +procedure THyperlinkForm.HTTP_FTP_Change(Sender: TObject); +begin + if RbHTTP.Checked then + InternetNotebook.PageIndex := 0; + if RbFTP.Checked then + InternetNotebook.PageIndex := 1; + UpdateHyperlinkInfo(nil); +end; + +procedure THyperlinkForm.SetHyperlink(AWorksheet: TsWorksheet; + const AHyperlink: TsHyperlink); +begin + SetWorksheet(AWorksheet); + SetHyperlinkTarget(AHyperlink.Target); + SetHyperlinkTooltip(AHyperlink.Tooltip); +end; + +procedure THyperlinkForm.SetHyperlinkKind(AValue: Integer); +var + i: Integer; +begin + for i:=0 to Toolbar.ButtonCount-1 do + Toolbar.Buttons[i].Down := (AValue = Toolbar.Buttons[i].Tag); + Notebook.PageIndex := AValue; +end; + +procedure THyperlinkForm.SetHyperlinkTarget(const AValue: String); +var + u: TURI; + sheet: TsWorksheet; + c,r: Cardinal; + i, idx: Integer; + p: Integer; + fn, bm: String; +begin + if AValue = '' then + begin + CbWorksheets.ItemIndex := 0; + CbCellAddress.Text := ''; + + CbMailRecipient.Text := ''; + EdMailSubject.Text := ''; + + UpdateHyperlinkInfo(nil); + exit; + end; + + // Internal link + if pos('#', AValue) = 1 then begin + SetHyperlinkKind(TAG_INTERNAL); + if FWorkbook.TryStrToCell(Copy(AValue, 2, Length(AValue)), sheet, r, c) then + begin + if (sheet = nil) or (sheet = FWorksheet) then + CbWorksheets.ItemIndex := 0 + else + begin + idx := 0; + for i:=1 to CbWorksheets.Items.Count-1 do + if CbWorksheets.Items[i] = sheet.Name then + begin + idx := i; + break; + end; + CbWorksheets.ItemIndex := idx; + end; + CbCellAddress.Text := GetCellString(r, c); + UpdateHyperlinkInfo(nil); + end else begin + HyperlinkInfo.Caption := AValue; + MessageDlg(Format('Sheet not found in hyperlink "%s"', [AValue]), mtError, + [mbOK], 0); + end; + exit; + end; + + // external links + u := ParseURI(AValue); + + // File with absolute path + if SameText(u.Protocol, 'file') then + begin + SetHyperlinkKind(TAG_FILE); + UriToFilename(AValue, fn); + CbFilename.Text := fn; + CbFileBookmark.Text := u.Bookmark; + UpdateHyperlinkInfo(nil); + exit; + end; + + // Mail + if SameText(u.Protocol, 'mailto') then + begin + SetHyperlinkKind(TAG_MAIL); + CbMailRecipient.Text := u.Document; + if CbMailRecipient.Items.IndexOf(u.Document) = -1 then + CbMailRecipient.Items.Insert(0, u.Document); + if (u.Params <> '') then + begin + p := pos('subject=', u.Params); + if p <> 0 then + EdMailSubject.Text := copy(u.Params, p+Length('subject='), MaxInt); + end; + UpdateHyperlinkInfo(nil); + exit; + end; + + // http + if SameText(u.Protocol, 'http') or SameText(u.Protocol, 'https') then + begin + SetHyperlinkKind(TAG_INTERNET); + SetInternetLinkKind(TAG_HTTP); + CbHttpAddress.Text := u.Host; + EdHttpBookmark.Text := u.Bookmark; + UpdateHyperlinkInfo(nil); + exit; + end; + + // ftp + if SameText(u.Protocol, 'ftp') then + begin + SetHyperlinkKind(TAG_INTERNET); + SetInternetLinkKind(TAG_FTP); + CbFtpServer.Text := u.Host; + CbFtpUserName.text := u.UserName; + CbFtpPassword.Text := u.Password; + UpdateHyperlinkInfo(nil); + exit; + end; + + // If we get there it must be a local file with relative path + SetHyperlinkKind(TAG_FILE); + SplitHyperlink(AValue, fn, bm); + CbFileName.Text := fn; + CbFileBookmark.Text := bm; + UpdateHyperlinkInfo(nil); +end; + +procedure THyperlinkForm.SetHyperlinkTooltip(const AValue: String); +begin + EdTooltip.Text := AValue; +end; + +procedure THyperlinkForm.SetInternetLinkKind(AValue: Integer); +begin + RbHttp.Checked := AValue = TAG_HTTP; + RbFtp.Checked := AValue = TAG_FTP; + InternetNotebook.PageIndex := AValue; +end; + +procedure THyperlinkForm.SetWorksheet(AWorksheet: TsWorksheet); +var + i: Integer; +begin + FWorksheet := AWorksheet; + if FWorksheet = nil then + raise Exception.Create('[THyperlinkForm.SetWorksheet] Worksheet cannot be nil.'); + FWorkbook := FWorksheet.Workbook; + + CbWorksheets.Items.Clear; + CbWorksheets.Items.Add('(current worksheet)'); + for i:=0 to FWorkbook.GetWorksheetCount-1 do + CbWorksheets.Items.Add(FWorkbook.GetWorksheetByIndex(i).Name); +end; + +procedure THyperlinkForm.ToolButtonClick(Sender: TObject); +var + i: Integer; +begin + Notebook.PageIndex := TToolButton(Sender).Tag; + for i:=0 to Toolbar.ButtonCount-1 do + Toolbar.Buttons[i].Down := Toolbar.Buttons[i].Tag = TToolbutton(Sender).Tag; + UpdateHyperlinkInfo(nil); +end; + +procedure THyperlinkForm.UpdateHyperlinkInfo(Sender: TObject); +var + s: String; +begin + s := GetHyperlinkTarget; + if s = '' then s := #32; + HyperlinkInfo.Caption := s; +end; + +function THyperlinkForm.ValidData(out AControl: TWinControl; + out AMsg: String): Boolean; +var + r,c: Cardinal; +begin + Result := false; + AMsg := ''; + AControl := nil; + + case GetHyperlinkKind of + TAG_INTERNAL: + begin + if CbCellAddress.Text = '' then + begin + AMsg := 'No cell address specified.'; + AControl := CbCellAddress; + exit; + end; + if not ParseCellString(CbCellAddress.Text, r, c) then + begin + AMsg := Format('"%s" is not a valid cell address.', [CbCellAddress.Text]); + AControl := CbCellAddress; + exit; + end; + if (CbWorksheets.Items.IndexOf(CbWorksheets.Text) = -1) and (CbWorksheets.ItemIndex <> 0) then + begin + AMsg := Format('Worksheet "%s" does not exist.', [CbWorksheets.Text]); + AControl := CbWorksheets; + exit; + end; + end; + + TAG_FILE: + begin + if CbFilename.Text = '' then + begin + AMsg := 'No filename specified.'; + AControl := CbFileName; + exit; + end; + end; + + TAG_INTERNET: + if RbHttp.Checked then + begin + if CbHttpAddress.Text = '' then + begin + AMsg := 'URL of web site not specified.'; + AControl := CbHttpAddress; + exit; + end; + end else + if RbFtp.Checked then + begin + if CbFtpServer.Text = '' then + begin + AMsg := 'Ftp server not specified.'; + AControl := CbFtpServer; + exit; + end; + end; + + TAG_MAIL: + begin + if CbMailRecipient.Text = '' then + begin + AMsg := 'No mail recipient specified.'; + AControl := CbMailRecipient; + exit; + end; + // Check e-mail address here also! + end; + end; + Result := true; +end; + +end. + diff --git a/applications/spready/smain.lfm b/applications/spready/smain.lfm new file mode 100644 index 000000000..6490caab4 --- /dev/null +++ b/applications/spready/smain.lfm @@ -0,0 +1,4869 @@ +object MainForm: TMainForm + Left = 267 + Height = 709 + Top = 152 + Width = 1120 + Caption = 'spready' + ClientHeight = 689 + ClientWidth = 1120 + Menu = MainMenu + OnCloseQuery = FormCloseQuery + OnCreate = FormCreate + OnShow = FormShow + ShowHint = True + LCLVersion = '1.7' + object WorkbookTabControl: TsWorkbookTabControl + Left = 0 + Height = 606 + Top = 83 + Width = 792 + TabIndex = 0 + Tabs.Strings = ( + 'Sheet1' + ) + Align = alClient + TabOrder = 0 + WorkbookSource = WorkbookSource + object WorksheetGrid: TsWorksheetGrid + Left = 2 + Height = 581 + Top = 23 + Width = 788 + AutoCalc = True + FrozenCols = 0 + FrozenRows = 0 + ReadFormulas = True + TextOverflow = True + WorkbookSource = WorkbookSource + Align = alClient + AutoAdvance = aaDown + ColCount = 27 + DefaultColWidth = 64 + DefaultRowHeight = 22 + Font.Color = clBlack + Font.Height = -13 + Font.Name = 'Arial' + MouseWheelOption = mwGrid + Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goRowSizing, goColSizing, goEditing, goThumbTracking, goDblClickAutoSize, goCellHints] + ParentFont = False + RowCount = 101 + TabOrder = 1 + TitleFont.Color = clBlack + TitleFont.Height = -13 + TitleFont.Name = 'Arial' + TitleStyle = tsNative + OnClickHyperlink = WorksheetGridClickHyperlink + OnMouseWheel = WorksheetGridMouseWheel + end + end + object InspectorTabControl: TTabControl + Left = 797 + Height = 606 + Top = 83 + Width = 323 + MultiLine = True + OnChange = InspectorTabControlChange + TabIndex = 0 + Tabs.Strings = ( + 'Workbook' + 'Worksheet' + 'Cell values' + 'Cell properties' + 'Row' + 'Column' + ) + Align = alRight + TabOrder = 1 + Visible = False + object Inspector: TsSpreadsheetInspector + Left = 2 + Height = 561 + Top = 43 + Width = 319 + Align = alClient + DefaultColWidth = 100 + MouseWheelOption = mwGrid + RowCount = 33 + TabOrder = 1 + TitleStyle = tsNative + OnEnter = InspectorEnter + OnExit = InspectorExit + DisplayOptions = [doColumnTitles] + Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goColSizing, goAlwaysShowEditor, goThumbTracking, goCellHints, goTruncCellHints, goCellEllipsis] + Strings.Strings = ( + 'FileName=' + 'FileFormat=(unknown)' + 'ActiveWorksheet=Sheet1' + 'Options=boAutoCalc, boCalcBeforeSaving, boReadFormulas' + '(-) FormatSettings=' + ' ThousandSeparator=.' + ' DecimalSeparator=,' + ' ListSeparator=;' + ' DateSeparator=.' + ' TimeSeparator=:' + ' ShortDateFormat=dd.MM.yy' + ' LongDateFormat=dd.MMM.yyyy' + ' ShortTimeFormat=hh:nn' + ' LongTimeFormat=hh:nn:ss' + ' TimeAMString=' + ' TimePMString=' + ' ShortMonthNames=Jan, Feb, Mrz, Apr, Mai, Jun, Jul, Aug, Sep, Okt, Nov, Dez' + ' LongMontNames=Januar, Februar, März, April, Mai, Juni, Juli, August, September, Oktober, November, Dezember' + ' ShortMonthNames=So, Mo, Di, Mi, Do, Fr, Sa' + ' LongMontNames=Sonntag, Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag' + ' CurrencyString=€' + ' PosCurrencyFormat=3' + ' NegCurrencyFormat=8' + ' TwoDigitYearCenturyWindow=50' + '(-) Images=' + '(-) Fonts=' + ' Font0=Arial; size 10; black' + ' Font1=Arial; size 10; blue; underline' + ' Font2=Arial; size 10; black; bold' + ' Font3=Arial; size 10; black; italic' + '(-) Cell formats=' + ' CellFormat0=nfGeneral' + ) + TitleCaptions.Strings = ( + 'Properties' + 'Values' + ) + WorkbookSource = WorkbookSource + Mode = imWorkbook + ExtendedColSizing = True + ColWidths = ( + 159 + 160 + ) + end + end + object InspectorSplitter: TSplitter + Left = 792 + Height = 606 + Top = 83 + Width = 5 + Align = alRight + ResizeAnchor = akRight + Visible = False + end + object ToolBar1: TToolBar + Left = 0 + Height = 26 + Top = 24 + Width = 1120 + AutoSize = True + ButtonHeight = 26 + ButtonWidth = 24 + Caption = 'ToolBar1' + EdgeBorders = [] + Images = ImageList + TabOrder = 3 + object ToolButton6: TToolButton + Left = 280 + Top = 0 + Action = AcFontBold + end + object ToolButton7: TToolButton + Left = 304 + Top = 0 + Action = AcFontItalic + end + object ToolButton8: TToolButton + Left = 328 + Top = 0 + Action = AcFontUnderline + end + object ToolButton10: TToolButton + Left = 376 + Height = 26 + Top = 0 + Width = 5 + Caption = 'ToolButton10' + Style = tbsDivider + end + object ToolButton11: TToolButton + Left = 352 + Top = 0 + Action = AcFontStrikeout + end + object ToolButton12: TToolButton + Left = 381 + Top = 0 + Action = AcHorAlignLeft + end + object ToolButton13: TToolButton + Left = 405 + Top = 0 + Action = AcHorAlignCenter + end + object ToolButton14: TToolButton + Left = 429 + Top = 0 + Action = AcHorAlignRight + end + object ToolButton15: TToolButton + Left = 453 + Height = 26 + Top = 0 + Width = 5 + Caption = 'ToolButton15' + Style = tbsDivider + end + object ToolButton16: TToolButton + Left = 458 + Top = 0 + Action = AcVertAlignTop + end + object ToolButton17: TToolButton + Left = 482 + Top = 0 + Action = AcVertAlignCenter + end + object ToolButton18: TToolButton + Left = 506 + Top = 0 + Action = AcVertAlignBottom + end + object ToolButton19: TToolButton + Left = 530 + Height = 26 + Top = 0 + Width = 5 + Caption = 'ToolButton19' + Style = tbsDivider + end + object ToolButton20: TToolButton + Left = 564 + Top = 0 + Action = AcNumFormatCustom + DropdownMenu = PuNumFormat + ImageIndex = 15 + Marked = True + Style = tbsDropDown + end + object ToolButton21: TToolButton + Left = 624 + Top = 0 + Action = AcNumFormatCustom + DropdownMenu = PuCurrencyFormat + ImageIndex = 17 + Style = tbsDropDown + end + object ToolButton22: TToolButton + Left = 600 + Top = 0 + Action = AcNumFormatPercentage + end + object ToolButton23: TToolButton + Left = 896 + Height = 26 + Top = 0 + Width = 5 + Caption = 'ToolButton23' + Style = tbsDivider + end + object ToolButton24: TToolButton + Left = 660 + Top = 0 + Action = AcNumFormatCustom + DropdownMenu = PuDateFormat + ImageIndex = 18 + Style = tbsDropDown + end + object ToolButton25: TToolButton + Left = 696 + Top = 0 + Action = AcNumFormatCustom + DropdownMenu = PuTimeFormat + ImageIndex = 19 + Style = tbsDropDown + end + object ToolButton26: TToolButton + Left = 732 + Top = 0 + Action = AcDecDecimals + end + object ToolButton27: TToolButton + Left = 756 + Top = 0 + Action = AcIncDecimals + end + object ToolButton29: TToolButton + Left = 30 + Hint = 'Cell font dialog' + Top = 0 + Action = AcCellFontDialog + end + object ToolButton30: TToolButton + Left = 785 + Hint = 'Background color dialog' + Top = 0 + Action = AcBackgroundColorDialog + end + object ToolButton31: TToolButton + Left = 855 + Height = 26 + Top = 0 + Width = 5 + Caption = 'ToolButton31' + Style = tbsDivider + end + object TbBorders: TToolButton + Left = 860 + Hint = 'Top border' + Top = 0 + Caption = 'Top' + DropdownMenu = PuBorders + ImageIndex = 26 + Style = tbsDropDown + end + object ToolButton3: TToolButton + Left = 780 + Height = 26 + Top = 0 + Width = 5 + Caption = 'ToolButton3' + Style = tbsDivider + end + object ToolButton5: TToolButton + Left = 901 + Top = 0 + Action = AcMergeCells + end + object ToolButton36: TToolButton + Left = 535 + Top = 0 + Action = AcWordWrap + end + object ToolButton37: TToolButton + Left = 1 + Top = 0 + Action = AcCopyFormat + end + object ToolButton38: TToolButton + Left = 25 + Height = 26 + Top = 0 + Width = 5 + Caption = 'ToolButton38' + Style = tbsDivider + end + object FontnameCombo: TsCellCombobox + Left = 54 + Height = 23 + Hint = 'Cell font name' + Top = 0 + Width = 130 + CellFormatItem = cfiFontName + WorkbookSource = WorkbookSource + DropDownCount = 24 + ItemIndex = 44 + TabOrder = 0 + Text = 'Arial' + end + object FontsizeCombo: TsCellCombobox + Left = 184 + Height = 23 + Hint = 'Cell font size' + Top = 0 + Width = 48 + CellFormatItem = cfiFontSize + WorkbookSource = WorkbookSource + DropDownCount = 24 + ItemIndex = 2 + TabOrder = 1 + Text = '10' + end + object FontColorCombobox: TsCellCombobox + Left = 232 + Height = 24 + Hint = 'Font color' + Top = 0 + Width = 48 + CellFormatItem = cfiFontColor + ColorRectOffset = 3 + ColorRectWidth = -1 + WorkbookSource = WorkbookSource + OnAddColors = ColorComboboxAddColors + DropDownCount = 24 + ItemIndex = 0 + TabOrder = 2 + end + object BackgroundColorCombobox: TsCellCombobox + Left = 809 + Height = 24 + Hint = 'Background color' + Top = 0 + Width = 46 + CellFormatItem = cfiBackgroundColor + ColorRectOffset = 3 + ColorRectWidth = -1 + WorkbookSource = WorkbookSource + OnAddColors = ColorComboboxAddColors + DropDownCount = 24 + ItemIndex = 0 + TabOrder = 3 + end + object ToolButton45: TToolButton + Left = 559 + Height = 26 + Top = 0 + Width = 5 + Caption = 'ToolButton45' + Style = tbsDivider + end + end + object ToolBar2: TToolBar + Left = 0 + Height = 24 + Top = 0 + Width = 1120 + AutoSize = True + ButtonHeight = 24 + ButtonWidth = 24 + Caption = 'ToolBar2' + EdgeBorders = [] + Images = ImageList + TabOrder = 4 + object ToolButton32: TToolButton + Left = 179 + Top = 0 + Action = AcAddWorksheet + end + object ToolButton33: TToolButton + Left = 203 + Top = 0 + Action = AcDeleteWorksheet + end + object ToolButton34: TToolButton + Left = 227 + Top = 0 + Action = acRenameWorksheet + end + object ToolButton1: TToolButton + Left = 357 + Height = 24 + Top = 0 + Width = 5 + Caption = 'ToolButton1' + Style = tbsDivider + end + object ToolButton2: TToolButton + Left = 545 + Top = 0 + Action = AcFileExit + end + object tbFileOpen: TToolButton + Left = 25 + Top = 0 + Action = AcFileOpen + DropdownMenu = PuRecentFiles + Style = tbsDropDown + end + object ToolButton28: TToolButton + Left = 251 + Height = 24 + Top = 0 + Width = 5 + Caption = 'ToolButton28' + Style = tbsDivider + end + object ToolButton35: TToolButton + Left = 61 + Top = 0 + Action = AcFileSaveAs + end + object ToolButton39: TToolButton + Left = 256 + Top = 0 + Action = AcColAdd + end + object ToolButton40: TToolButton + Left = 280 + Top = 0 + Action = AcColDelete + end + object ToolButton41: TToolButton + Left = 309 + Top = 0 + Action = AcRowAdd + end + object ToolButton42: TToolButton + Left = 333 + Top = 0 + Action = AcRowDelete + end + object ToolButton43: TToolButton + Left = 174 + Height = 24 + Top = 0 + Width = 5 + Caption = 'ToolButton43' + Style = tbsDivider + end + object ToolButton44: TToolButton + Left = 304 + Height = 24 + Top = 0 + Width = 5 + Caption = 'ToolButton44' + Style = tbsDivider + end + object ToolButton46: TToolButton + Left = 90 + Top = 0 + Action = AcCopyToClipboard + end + object ToolButton47: TToolButton + Left = 114 + Top = 0 + Action = AcCutToClipboard + end + object ToolButton48: TToolButton + Left = 138 + Top = 0 + Action = AcPasteAllFromClipboard + DropdownMenu = PuPaste + Style = tbsDropDown + end + object ToolButton49: TToolButton + Left = 85 + Height = 24 + Top = 0 + Width = 5 + Caption = 'ToolButton49' + Style = tbsDivider + end + object TbCommentAdd: TToolButton + Left = 362 + Top = 0 + Action = AcCommentNew + end + object TbCommentDelete: TToolButton + Left = 386 + Top = 0 + Action = AcCommentEdit + end + object TbCommentEdit: TToolButton + Left = 410 + Top = 0 + Action = AcCommentDelete + end + object ToolButton52: TToolButton + Left = 434 + Height = 24 + Top = 0 + Width = 5 + Caption = 'ToolButton52' + Style = tbsDivider + end + object ToolButton50: TToolButton + Left = 439 + Top = 0 + Action = AcHyperlinkNew + end + object ToolButton51: TToolButton + Left = 463 + Top = 0 + Action = AcHyperlinkEdit + end + object ToolButton53: TToolButton + Left = 487 + Top = 0 + Action = AcHyperlinkDelete + end + object ToolButton54: TToolButton + Left = 511 + Height = 24 + Top = 0 + Width = 5 + Caption = 'ToolButton54' + Style = tbsDivider + end + object ToolButton4: TToolButton + Left = 516 + Top = 0 + Action = AcSearch + end + object ToolButton55: TToolButton + Left = 540 + Height = 24 + Top = 0 + Width = 5 + Caption = 'ToolButton55' + Style = tbsDivider + end + object ToolButton9: TToolButton + Left = 1 + Top = 0 + Action = AcFileNew + end + end + object ToolBar3: TToolBar + Left = 0 + Height = 28 + Top = 50 + Width = 1120 + AutoSize = True + Caption = 'ToolBar3' + Constraints.MinHeight = 28 + EdgeBorders = [ebBottom] + TabOrder = 5 + object Panel2: TPanel + Left = 1 + Height = 26 + Top = 0 + Width = 138 + Align = alLeft + BevelOuter = bvNone + ClientHeight = 26 + ClientWidth = 138 + TabOrder = 0 + object CellIndicator: TsCellIndicator + Left = 0 + Height = 23 + Top = 0 + Width = 138 + Align = alTop + TabOrder = 0 + Text = 'A1' + WorkbookSource = WorkbookSource + end + end + object CellEdit: TsCellEdit + Left = 144 + Height = 23 + Top = 0 + Width = 974 + Align = alClient + BorderSpacing.Right = 2 + BorderSpacing.Bottom = 3 + TabOrder = 1 + WantReturns = False + WorkbookSource = WorkbookSource + end + object Splitter2: TSplitter + Left = 139 + Height = 26 + Top = 0 + Width = 5 + end + end + object Splitter3: TSplitter + Cursor = crVSplit + Left = 0 + Height = 5 + Top = 78 + Width = 1120 + Align = alTop + ResizeAnchor = akTop + end + object WorkbookSource: TsWorkbookSource + AutoDetectFormat = False + FileFormat = sfUser + Options = [boAutoCalc, boCalcBeforeSaving, boReadFormulas] + left = 176 + top = 160 + end + object OpenDialog: TOpenDialog + DefaultExt = '.xls' + Filter = 'All spreadsheet files|*.xls;*.xlsx;*.ods;*.csv|All Excel files (*.xls, *.xlsx)|*.xls;*.xlsx|Excel XML spreadsheet (*.xlsx)|*.xlsx|Excel XP/2003 XML spreadsheet (*.xml)|*.xml|Excel 97-2003 spreadsheets (*.xls)|*.xls|Excel 5 spreadsheet (*.xls)|*.xls|Excel 2.1 spreadsheets (*.xls)|*.xls|LibreOffice/OpenOffice spreadsheet (*.ods)|*.ods|HTML files (*.html; *.htm)|*.html;*.htm|Comma-separated text files (*.csv; *.txt)|*.csv;*.txt' + Options = [ofExtensionDifferent, ofEnableSizing, ofViewDetail] + left = 312 + top = 160 + end + object ActionList: TActionList + Images = ImageList + OnUpdate = ActionListUpdate + left = 176 + top = 248 + object AcAddWorksheet: TsWorksheetAddAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Add worksheet' + Hint = 'Add empty worksheet' + ImageIndex = 1 + NameMask = 'Sheet%d' + end + object AcDeleteWorksheet: TsWorksheetDeleteAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Delete worksheet...' + Hint = 'Delete worksheet' + ImageIndex = 2 + end + object acRenameWorksheet: TsWorksheetRenameAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Rename...' + Hint = 'Rename worksheet' + ImageIndex = 3 + end + object AcFontBold: TsFontStyleAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Bold' + Hint = 'Bold' + ImageIndex = 4 + FontStyle = fssBold + end + object AcFontItalic: TsFontStyleAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Italic' + Hint = 'Italic' + ImageIndex = 5 + FontStyle = fssItalic + end + object AcFontUnderline: TsFontStyleAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Underline' + Hint = 'Underline' + ImageIndex = 6 + FontStyle = fssUnderline + end + object AcFontStrikeout: TsFontStyleAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Strikeout' + Hint = 'Strikeout' + ImageIndex = 7 + FontStyle = fssStrikeOut + end + object AcVertAlignTop: TsVertAlignmentAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Top' + Hint = 'Top-aligned text' + ImageIndex = 11 + VertAlignment = vaTop + end + object AcVertAlignCenter: TsVertAlignmentAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Center' + Hint = 'Vertically centered text' + ImageIndex = 12 + VertAlignment = vaCenter + end + object AcVertAlignBottom: TsVertAlignmentAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Bottom' + Hint = 'Bottom-aligned text' + ImageIndex = 13 + VertAlignment = vaBottom + end + object AcHorAlignLeft: TsHorAlignmentAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Left' + Hint = 'Left-aligned text' + ImageIndex = 8 + HorAlignment = haLeft + end + object AcHorAlignCenter: TsHorAlignmentAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Center' + Hint = 'Centered text' + ImageIndex = 9 + HorAlignment = haCenter + end + object AcHorAlignRight: TsHorAlignmentAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Right' + Hint = 'Right-aligned text' + ImageIndex = 10 + HorAlignment = haRight + end + object AcWordWrap: TsWordwrapAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Word-wrap' + Hint = 'Word-wrapped text' + ImageIndex = 24 + end + object AcTextRotHor: TsTextRotationAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Horizontal text' + end + object AcTextRot90CW: TsTextRotationAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '90° clockwise' + Hint = '90° clockwise rotated text' + TextRotation = rt90DegreeClockwiseRotation + end + object AcTextRot90CCW: TsTextRotationAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '90° counter-clockwise' + Hint = '90° counter-clockwise rotated text' + TextRotation = rt90DegreeCounterClockwiseRotation + end + object AcTextRotStacked: TsTextRotationAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Stacked' + Hint = 'Vertically stacked horizontal letters' + TextRotation = rtStacked + end + object AcNumFormatCustom: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Custom...' + Hint = 'Custom number format' + NumberFormat = nfCustom + OnGetNumberFormatString = AcNumFormatCustomGetNumberFormatString + end + object AcNumFormatGeneral: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'General' + Hint = 'General format' + end + object AcNumFormatFixed: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Fixed' + Hint = 'Fixed decimals format' + NumberFormat = nfFixed + end + object AcNumFormatFixedTh: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Fixed w/thousand separator' + Hint = 'Fixed decimal count with thousand separator' + NumberFormat = nfFixedTh + end + object AcNumFormatPercentage: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Percent' + Hint = 'Percent format' + ImageIndex = 16 + NumberFormat = nfPercentage + end + object AcNumFormatCurrency: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Currency' + Hint = 'Currency format' + NumberFormat = nfCurrency + end + object AcNumFormatCurrencyRed: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Currency (red)' + Hint = 'Currency format (negative values in red)' + NumberFormat = nfCurrencyRed + end + object AcNumFormatExp: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Exponential' + Hint = 'Exponential format' + NumberFormat = nfExp + end + object AcNumFormatFraction1: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Fraction (1 digit)' + NumberFormat = nfFraction + NumberFormatString = '# ?/?' + end + object AcNumFormatFraction2: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Fraction (2 digits)' + NumberFormat = nfFraction + NumberFormatString = '# ??/??' + end + object AcNumFormatFraction3: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Fraction (3 digits)' + NumberFormat = nfFraction + NumberFormatString = '# ???/???' + end + object AcNumFormatDateTime: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Date/time' + Hint = 'Date and time' + NumberFormat = nfShortDateTime + end + object AcNumFormatLongDate: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Long date' + Hint = 'Long date format' + NumberFormat = nfLongDate + end + object AcNumFormatShortDate: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Short date' + Hint = 'Short date format' + NumberFormat = nfShortDate + end + object AcNumFormatDayMonth: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Day and month' + Hint = 'Day and month only' + NumberFormat = nfDayMonth + end + object AcNumFormatMonthYear: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Month and year' + Hint = 'Month and year only' + NumberFormat = nfMonthYear + end + object AcNumFormatLongTime: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Long time' + Hint = 'Long time foramt' + NumberFormat = nfLongTime + end + object AcNumFormatShortTime: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Short time' + Hint = 'Short time format' + NumberFormat = nfShortTime + end + object AcNumFormatLongTimeAM: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Long time AM/PM' + Hint = 'Long 12-hour time format' + NumberFormat = nfLongTimeAM + end + object AcNumFormatShortTimeAM: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Short time AM/PM' + Hint = 'Short 12-hour time format' + NumberFormat = nfShortTimeAM + end + object AcNumFormatTimeInterval: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Time interval' + Hint = 'Time interval format' + NumberFormat = nfTimeInterval + end + object AcNumFormatText: TsNumberFormatAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Text' + Hint = 'Text format' + NumberFormat = nfText + end + object AcViewInspector: TAction + Category = 'View' + AutoCheck = True + Caption = 'Inspector' + OnExecute = AcViewInspectorExecute + end + object AcRowAdd: TAction + Category = 'Worksheet' + Caption = 'Add row' + Hint = 'Add row' + ImageIndex = 48 + OnExecute = AcRowAddExecute + end + object AcColAdd: TAction + Category = 'Worksheet' + Caption = 'Add column' + Hint = 'Add column' + ImageIndex = 47 + OnExecute = AcColAddExecute + end + object AcRowDelete: TAction + Category = 'Worksheet' + Caption = 'Delete row' + Hint = 'Delete row' + ImageIndex = 50 + OnExecute = AcRowDeleteExecute + end + object AcColDelete: TAction + Category = 'Worksheet' + Caption = 'Delete column' + Hint = 'Delete column' + ImageIndex = 49 + OnExecute = AcColDeleteExecute + end + object AcSettingsFormatSettings: TAction + Category = 'Settings' + Caption = 'Number format settings...' + Hint = 'Define number format settings' + OnExecute = AcSettingsFormatSettingsExecute + end + object AcSettingsCSVParams: TAction + Category = 'Settings' + Caption = 'CSV parameters...' + Hint = 'Parameters for CSV files' + OnExecute = AcSettingsCSVParamsExecute + end + object AcSettingsCurrency: TAction + Category = 'Settings' + Caption = 'Currency symbols...' + Hint = 'Define currency symbols' + OnExecute = AcSettingsCurrencyExecute + end + object AcSearch: TAction + Category = 'Edit' + Caption = 'Search...' + Hint = 'Search for cells' + ImageIndex = 70 + OnExecute = AcSearchExecute + ShortCut = 16454 + end + object AcShowGridLines: TAction + Category = 'View' + AutoCheck = True + Caption = 'Grid lines' + Checked = True + OnExecute = AcShowGridLinesExecute + OnUpdate = AcShowGridLinesUpdate + end + object AcShowHeaders: TAction + Category = 'View' + AutoCheck = True + Caption = 'Show column/row headers' + Checked = True + OnExecute = AcShowHeadersExecute + OnUpdate = AcShowHeadersUpdate + end + object AcFrozenRows: TAction + Category = 'Worksheet' + AutoCheck = True + Caption = 'Frozen rows' + OnExecute = AcFrozenRowsExecute + OnUpdate = AcFrozenRowsUpdate + end + object AcFrozenCols: TAction + Category = 'Worksheet' + AutoCheck = True + Caption = 'Frozen columns' + OnExecute = AcFrozenColsExecute + OnUpdate = AcFrozenColsUpdate + end + object AcWorksheetRTL: TAction + Category = 'Worksheet' + AutoCheck = True + Caption = 'Text direction inverted' + OnExecute = AcWorksheetRTLExecute + OnUpdate = AcWorksheetRTLUpdate + end + object AcIncDecimals: TsDecimalsAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'More decimals' + ImageIndex = 21 + end + object AcDecDecimals: TsDecimalsAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Less decimals' + ImageIndex = 20 + Delta = -1 + end + object AcCellFontDialog: TsFontDialogAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Cell font...' + Hint = 'Cell font' + ImageIndex = 14 + Dialog.MinFontSize = 0 + Dialog.MaxFontSize = 0 + end + object AcBackgroundColorDialog: TsBackgroundColorDialogAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Background color...' + Hint = 'Background color' + ImageIndex = 22 + Dialog.Color = clBlack + Dialog.CustomColors.Strings = ( + 'ColorA=000000' + 'ColorB=000080' + 'ColorC=008000' + 'ColorD=008080' + 'ColorE=800000' + 'ColorF=800080' + 'ColorG=808000' + 'ColorH=808080' + 'ColorI=C0C0C0' + 'ColorJ=0000FF' + 'ColorK=00FF00' + 'ColorL=00FFFF' + 'ColorM=FF0000' + 'ColorN=FF00FF' + 'ColorO=FFFF00' + 'ColorP=FFFFFF' + 'ColorQ=C0DCC0' + 'ColorR=F0CAA6' + 'ColorS=F0FBFF' + 'ColorT=A4A0A0' + ) + end + object AcCellBorderNone: TsNoCellBordersAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '(none)' + Hint = 'No borders' + ImageIndex = 26 + end + object AcCellBorderTop: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = True + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = False + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'Top' + Hint = 'Top border' + ImageIndex = 31 + end + object AcCellBorderInnerHor: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = False + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = False + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = True + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'Inner horizontal' + Hint = 'Inner horizontal border' + ImageIndex = 38 + end + object AcCellBorderBottom: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = False + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = True + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'Bottom' + Hint = 'Bottom border' + ImageIndex = 32 + end + object AcCellBorderBottomThick: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = False + Borders.South.LineStyle = lsMedium + Borders.South.Color = clBlack + Borders.South.Visible = True + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'Bottom thick' + Hint = 'Thick bottom border' + ImageIndex = 33 + end + object AcCellBorderBottomDbl: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = False + Borders.South.LineStyle = lsDouble + Borders.South.Color = clBlack + Borders.South.Visible = True + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'Bottom double' + Hint = 'Double bottom border' + ImageIndex = 34 + end + object AcCellBorderTopBottomThick: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = True + Borders.South.LineStyle = lsMedium + Borders.South.Color = clBlack + Borders.South.Visible = True + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'Top & bottom thick' + Hint = 'Top and thick bottom borders' + ImageIndex = 36 + end + object AcCellBorderTopBottomDbl: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = True + Borders.South.LineStyle = lsDouble + Borders.South.Color = clBlack + Borders.South.Visible = True + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'Top and double bottom' + Hint = 'Top and double bottom borders' + ImageIndex = 37 + end + object AcCellBorderAllHor: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = True + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = True + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = True + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'All horizontal' + Hint = 'All horizontal borders' + ImageIndex = 39 + end + object AcCellBorderLeft: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = False + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = False + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = True + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'Left' + Hint = 'Left border' + ImageIndex = 40 + end + object AcCellBorderRight: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = True + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = False + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = False + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'Right' + Hint = 'Right border' + ImageIndex = 41 + end + object AcCellBorderInnerVert: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = False + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = False + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = True + Caption = 'Inner vertical' + Hint = 'Inner vertical border' + ImageIndex = 42 + end + object AcCellBorderAllVert: TsCellBorderAction + Category = 'FPSpreadsheet' + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = True + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = False + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = False + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = True + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = True + Caption = 'All vertical' + Hint = 'All vertical borders' + ImageIndex = 43 + end + object AcCellBorderDiagUp: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = False + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = False + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = True + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'Diagonal up' + Hint = 'Diagonal border, bottom-left to top-right' + ImageIndex = 63 + end + object AcCellBorderDiagDown: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = False + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = False + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = False + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = False + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = True + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'Diagonal down' + Hint = 'Diagonal border, top-left to bottom-right' + ImageIndex = 64 + end + object AcCellBorderAllOuter: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = True + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = True + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = True + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = True + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'All outer (thin)' + Hint = 'All outer borders (thin)' + ImageIndex = 28 + end + object AcCellBorderAllOuterThick: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsMedium + Borders.East.Color = clBlack + Borders.East.Visible = True + Borders.North.LineStyle = lsMedium + Borders.North.Color = clBlack + Borders.North.Visible = True + Borders.South.LineStyle = lsMedium + Borders.South.Color = clBlack + Borders.South.Visible = True + Borders.West.LineStyle = lsMedium + Borders.West.Color = clBlack + Borders.West.Visible = True + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = False + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = False + Caption = 'All outer (thick)' + Hint = 'All outer borders (thick)' + ImageIndex = 27 + end + object AcCellBorderAll: TsCellBorderAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Borders.East.LineStyle = lsThin + Borders.East.Color = clBlack + Borders.East.Visible = True + Borders.North.LineStyle = lsThin + Borders.North.Color = clBlack + Borders.North.Visible = True + Borders.South.LineStyle = lsThin + Borders.South.Color = clBlack + Borders.South.Visible = True + Borders.West.LineStyle = lsThin + Borders.West.Color = clBlack + Borders.West.Visible = True + Borders.DiagonalUp.LineStyle = lsThin + Borders.DiagonalUp.Color = clBlack + Borders.DiagonalUp.Visible = False + Borders.DiagonalDown.LineStyle = lsThin + Borders.DiagonalDown.Color = clBlack + Borders.DiagonalDown.Visible = False + Borders.InnerHor.LineStyle = lsThin + Borders.InnerHor.Color = clBlack + Borders.InnerHor.Visible = True + Borders.InnerVert.LineStyle = lsThin + Borders.InnerVert.Color = clBlack + Borders.InnerVert.Visible = True + Caption = 'All' + Hint = 'All borders (thin)' + ImageIndex = 29 + end + object AcMergeCells: TsMergeAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Merge' + Hint = 'Merge cells' + ImageIndex = 23 + end + object AcCopyFormat: TsCopyAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Copy format' + Hint = 'Copy format' + ImageIndex = 46 + end + object AcCopyToClipboard: TsCopyAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Copy' + CopyMode = cmCopy + ImageIndex = 51 + ShortCut = 16451 + end + object AcCutToClipboard: TsCopyAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Cut' + CopyMode = cmCut + ImageIndex = 52 + ShortCut = 16472 + end + object AcPasteAllFromClipboard: TsCopyAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Paste all' + CopyItem = ciAll + CopyMode = cmPaste + ImageIndex = 53 + ShortCut = 16470 + end + object AcPasteValueFromClipboard: TsCopyAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Paste value' + CopyItem = ciValue + CopyMode = cmPaste + end + object AcPasteFormatFromClipboard: TsCopyAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Paste format' + CopyMode = cmPaste + end + object AcPasteFormulaFromClipboard: TsCopyAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = 'Paste formula' + CopyItem = ciFormula + CopyMode = cmPaste + end + object AcCommentNew: TsCellCommentAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Mode = ccmNew + Caption = 'New comment' + Hint = 'New comment' + ImageIndex = 54 + end + object AcCommentEdit: TsCellCommentAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Mode = ccmEdit + Caption = 'Edit comment...' + Hint = 'Edit comment' + ImageIndex = 56 + end + object AcCommentDelete: TsCellCommentAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Mode = ccmDelete + Caption = 'Delete comment' + Hint = 'Delete comment' + ImageIndex = 55 + end + object AcHyperlinkNew: TsCellHyperlinkAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Mode = chmNew + OnHyperlink = HyperlinkHandler + Caption = 'New hyperlink...' + Hint = 'Add hyperlink to active cell' + ImageIndex = 57 + end + object AcHyperlinkEdit: TsCellHyperlinkAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Mode = chmEdit + OnHyperlink = HyperlinkHandler + Caption = 'Edit hyperlink...' + Hint = 'Edit hyperlink of selected cell' + ImageIndex = 59 + end + object AcHyperlinkDelete: TsCellHyperlinkAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Mode = chmDelete + Caption = 'Delete hyperlink' + Hint = 'Delete hyperlink from selected cell' + ImageIndex = 58 + end + object AcZoom30: TsWorksheetZoomAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '30%' + Hint = 'Zoom factor 30%' + Zoom = 30 + end + object AcZoom50: TsWorksheetZoomAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '50%' + Hint = 'Zoom factor 50%' + Zoom = 50 + end + object AcZoom75: TsWorksheetZoomAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '75%' + Hint = 'Zoom factor 75%' + Zoom = 75 + end + object AcZoom90: TsWorksheetZoomAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '90%' + Hint = 'Zoom factor 90%' + Zoom = 90 + end + object AcZoom100: TsWorksheetZoomAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '100%' + Hint = 'Zoom factor 100%' + end + object AcZoom150: TsWorksheetZoomAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '150%' + Hint = 'Zoom factor 150%' + Zoom = 150 + end + object AcZoom200: TsWorksheetZoomAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '200%' + Hint = 'Zoom factor 200%' + Zoom = 200 + end + object AcZoom300: TsWorksheetZoomAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '300%' + Hint = 'Zoom factor 300%' + Zoom = 300 + end + object AcZoom500: TsWorksheetZoomAction + Category = 'FPSpreadsheet' + WorkbookSource = WorkbookSource + Caption = '500%' + Hint = 'Zoom factor 500%' + Zoom = 500 + end + object AcAutoRowHeights: TAction + Category = 'Edit' + Caption = 'Auto row heights' + Hint = 'Automatic row height adjustment' + OnExecute = AcAutoRowHeightsExecute + end + object AcFileNew: TAction + Category = 'File' + Caption = 'New...' + Hint = 'New spreadsheet' + ImageIndex = 71 + OnExecute = AcFileNewExecute + end + object AcFileOpen: TFileOpen + Category = 'File' + Caption = '&Open ...' + Dialog.Filter = 'All spreadsheet files|*.xls;*.xlsx;*.ods;*.csv|All Excel files (*.xls, *.xlsx)|*.xls;*.xlsx|Excel XML spreadsheets (*.xlsx)|*.xlsx|Excel XP/2003 XML spreadsheets (*.xml)|*.xml|Excel 97-2003 spreadsheets (*.xls)|*.xls|Excel 5 spreadsheets (*.xls)|*.xls|Excel 2.1 spreadsheets (*.xls)|*.xls|LibreOffice/OpenOffice spreadsheets (*.ods)|*.ods|HTML files (*.html; *.htm)|*.html;*.htm|Comma-separated text files (*.csv; *.txt)|*.csv;*.txt' + Dialog.Options = [ofExtensionDifferent, ofFileMustExist, ofEnableSizing, ofViewDetail] + Hint = 'Open spreadsheet file' + ImageIndex = 44 + ShortCut = 16463 + OnAccept = AcFileOpenAccept + end + object AcFileSaveAs: TFileSaveAs + Category = 'File' + Caption = 'Save &as ...' + Dialog.Title = 'AcSaveFileAs' + Dialog.Filter = 'Excel XML spreadsheet (*.xlsx)|*.xlsx|Excel XP/2003 XML spreadsheets (*.xml)|*.xml|Excel 97-2003 spreadsheets (*.xls)|*.xls|Excel 5 spreadsheet (*.xls)|*.xls|Excel 2.1 spreadsheets (*.xls)|*.xls|LibreOffice/OpenOffice spreadsheet (*.ods)|*.ods|Comma-delimited files (*.csv)|*.csv|HTML files (*.html; *.htm)|*.html;*.htm|WikiTable (WikiMedia-Format, *.wikitable_wikimedia)|*.wikitable_wikimedia' + Dialog.OnTypeChange = TSaveDialogTypeChange + Hint = 'Save spreadsheet' + ImageIndex = 45 + BeforeExecute = AcFileSaveAsBeforeExecute + OnAccept = AcFileSaveAsAccept + end + object AcFileExit: TFileExit + Category = 'File' + Caption = 'E&xit' + Hint = 'Exit' + ImageIndex = 0 + ShortCut = 32856 + end + object AcAbout: TAction + Category = 'Help' + Caption = 'About Spready...' + Hint = 'About this program' + ImageIndex = 72 + OnExecute = AcAboutExecute + end + object AcSort: TAction + Category = 'Edit' + Caption = 'Sort...' + Hint = 'Sort selected range' + OnExecute = AcSortExecute + end + object AcSortColAsc: TAction + Category = 'Edit' + Caption = 'Sort column only (ascending)' + Hint = 'Sort current column in ascending order' + OnExecute = AcSortColAscExecute + end + object AcRowHeight: TAction + Category = 'Edit' + Caption = 'Row height...' + Hint = 'Set height of current row' + OnExecute = AcRowHeightExecute + end + object AcColWidth: TAction + Category = 'Edit' + Caption = 'Column width...' + Hint = 'Set width of current column' + OnExecute = AcColWidthExecute + end + end + object ImageList: TImageList + left = 176 + top = 312 + Bitmap = { + 4C69490000001000000010000000003F9300003F9300003F9300003F9424003F + 948A003E93CC004095CC004095CC004095CC004095CC004095CC004095CC0040 + 95CC004095CC00409599003F9400003F9300003F9324003F938A0E4B9CD33F76 + C0EC5D90D4FF3365A9FFA0A0A0FFA9A9A9FFA9A9A9FFAAAAAAFFACACACFFAEAE + AEFFB0B0B0FF003E93CC003E9300003F938A0E4A9CD33E75BFEC5487CBFF3669 + ADFF23569AFF3363A6FFA9A9A9FFBCBCBCFFBDBDBDFFBFBFBFFFC1C1C1FFC4C4 + C4FFC7C7C7FF003C90CC003C9000003D91CC5D90D4FF3568ACFF285B9FFF1A4D + 91FF4477BBFF3361A4FFA9A9A9FFBDBDBDFFBFBFBFFFC1C1C1FFC4C4C4FFC7C7 + C7FFC9C9C9FF003A8DCC003A8D00003B8ECC588BCFFF1A4D91FF4376BAFF3265 + A9FF4376BAFF335FA1FFAAAAAAFFBFBFBFFFC1C1C1FFC4C4C4FFB1B1B1FFBBBB + BBFFCCCCCCFF003789CC0037890000398BCC5588CCFF275A9EFF4174B8FF3164 + A8FF4174B8FF335D9EFFACACACFFC1C1C1FFC4C4C4FFC7C7C7FFA8A8A8FFA8A8 + A8FFBEBEBEFF003485CC00348500003688CC5386CAFF295CA0FF3F72B6FF3063 + A7FF3F72B6FF335A9AFFAEAEAEFFACACACFFA5A5A5FFA5A5A5FFA5A5A5FFFDFD + FDFFA5A5A5FF122F609510295100003485CC5083C7FF1D5094FF3265A9FF2D60 + A4FF3D70B4FF335897FFB0B0B0FFA2A2A2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2 + F2FFF2F2F2FF1A1A1A661A1A1A1A003181CC4C7FC3FFBBBBBBFF22518CFF2C5F + A3FF3B6EB2FF335593FFB3B3B3FFAAAAAAFFA0A0A0FFA0A0A0FFA0A0A0FFE4E4 + E4FFA0A0A0FF051E4D950B204600002E7DCC497CC0FF09336FFF215090FF2B5E + A2FF396CB0FF335290FFB5B5B5FFCCCCCCFFD0D0D0FFD3D3D3FF9D9D9DFF9D9D + 9DFFBFBFBFFF002774CC00277400002B79CC477ABEFF2C5FA3FF376AAEFF2B5E + A2FF376AAEFF33508CFFB8B8B8FFD0D0D0FFD3D3D3FFD5D5D5FFAAAAAAFFBEBE + BEFFDCDCDCFF00246FCC00246F00002875CC4477BBFF2C5FA3FF3568ACFF2B5E + A2FF2E61A5FF334B87FFBBBBBBFFD3D3D3FFD5D5D5FFD8D8D8FFDBDBDBFFDCDC + DCFFDDDDDDFF001F68CC001F6800002571CC4174B8FF2C5FA3FF2D60A4FF2356 + 9AFF3D70B4FF334179FFBEBEBEFFD5D5D5FFD8D8D8FFDBDBDBFFDCDCDCFFDDDD + DDFFDDDDDDFF001258CC0012580000226DCC3F72B6FF225599FF3B6EB2FF2C51 + 96EC0A1C60D3000749A4000648CC000648CC000648CC000648CC000648CC0006 + 48CC000648CC00074A9900084B00001B64CC4174B8FF2A5094EC0A1A5ED30008 + 4A8A000648240006470000044500000445000004450000044500000445000004 + 4500000445000006480000084B0000105500000B4FCC0007498A000546240005 + 4700000648000006470000044500000445000004450000044500000445000004 + 4500000445000006480000084B007E7E7E007E7E7E007F7F7F00808080008080 + 800080808000808080008080800080808000129D000014A8000015A9009915A9 + 00CC15A9009914A80000129D00007E7E7E007E7E7E007F7F7F00808080008080 + 800080808000808080008080800080808000129D000013A1000014A400CC75EE + 64FF14A400CC13A10000129D00007E7E7E007E7E7E007F7F7F00808080008080 + 800080808000808080008080800080808000129C0099129D00CC129D00CC66EB + 55FF129D00CC129D00CC129C00997E7E7E007E7E7E007F7F7F227F7F7F597F7F + 7F667F7F7F667F7F7F667F7F7F667F7F7F661A930CE052E741FF52E741FF52E7 + 41FF52E741FF52E741FF109500CC7A7A7A007A7A7A007A7A7A5AE9E9E9D3FFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6EBB66FF3EA333FF3EA333FF3DE2 + 2CFF178B0BDF0E8C00CC0E8D0099727272007272720072727268FCFCFCFFFBFB + FBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFF3C9B32FF2BDF + 1AFF16810BE10F8703000E8C00006A6A6A006A6A6A006A6A6A6AF8F8F8FFF6F6 + F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FF66A362FF3686 + 32FF266B22C43C6C39003B7A340058585800616161006161616BF4F4F4FFF0F0 + F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF4F4 + F4FF6161616B61616100585858004C4C4C00515151005656566CEFEFEFFFEAEA + EAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFFEFEF + EFFF5656566C515151004C4C4C004B4B4B534C4C4C6E4C4C4C6EEBEBEBFFE4E4 + E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFEBEB + EBFF4C4C4C6E4C4C4C6E4B4B4B533C3C3C70F0F0F0FFF0F0F0FFECECECFFE8E8 + E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFECEC + ECFFF0F0F0FFF0F0F0FF3C3C3C701B1B1B581717177517171775171717751717 + 1775171717751717177517171775171717751717177517171775171717751717 + 177517171775171717751B1B1B58FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF007E7E7E007E7E7E007F7F7F00808080008080 + 8000808080008080800080808000808080000000A6990000A7CC0000A7CC0000 + A7CC0000A7CC0000A7CC0000A6997E7E7E007E7E7E007F7F7F227F7F7F597F7F + 7F667F7F7F667F7F7F667F7F7F667F7F7F660C0C95E05E5EF7FF5E5EF7FF5E5E + F7FF5E5EF7FF5E5EF7FF000098CC7A7A7A007A7A7A007A7A7A5AE9E9E9D3FFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6666B4FF333399FF333399FF2828 + 92F60B0B7FDF000080CC00008499727272007272720072727268FCFCFCFFFBFB + FBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFCFC + FCFF727272681C1C7600000080006A6A6A006A6A6A006A6A6A6AF8F8F8FFF6F6 + F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF8F8 + F8FF6A6A6A6A6A6A6A003434740058585800616161006161616BF4F4F4FFF0F0 + F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF4F4 + F4FF6161616B61616100585858004C4C4C00515151005656566CEFEFEFFFEAEA + EAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFFEFEF + EFFF5656566C515151004C4C4C004B4B4B534C4C4C6E4C4C4C6EEBEBEBFFE4E4 + E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFEBEB + EBFF4C4C4C6E4C4C4C6E4B4B4B533C3C3C70F0F0F0FFF0F0F0FFECECECFFE8E8 + E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFECEC + ECFFF0F0F0FFF0F0F0FF3C3C3C701B1B1B581717177517171775171717751717 + 1775171717751717177517171775171717751717177517171775171717751717 + 177517171775171717751B1B1B58FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF007E7E7E007E7E7E007F7F7F00808080008080 + 800080808000808080008080800080808000808080006E85890001A3BB005555 + 55002B2B9D390101DEAF0101C6407E7E7E007E7E7E007F7F7F00808080008080 + 800080808000808080008080800080808000808080006E85890001A3BB005454 + 542438386F7C8080FFFF0101B1C17E7E7E007E7E7E007F7F7F00808080008080 + 800080808000808080008080800080808000808080006E85890001A2BA3F4A4A + 4A6CF7F7F7FF1A1A468E00009F467E7E7E007E7E7E007F7F7F227F7F7F597F7F + 7F667F7F7F667F7F7F667F7F7F667F7F7F667F7F7F66538B948C1494A9D379E6 + F7FF2D2D2D8F1212122E00009C007A7A7A007A7A7A007A7A7A5AE9E9E9D3FFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1E8EEFF4BB6C7FF79E6F7FF3496 + A8F44D6F7681444444003C3C8A00727272007272720072727268FCFCFCFFFBFB + FBFFFBFBFBFFFBFBFBFFFBFBFBFFBFE5EBFF4AB4C5FF79E6F7FF419EAFFFB9D8 + DEFF7272726872727200727272006A6A6A006A6A6A006A6A6A6AF8F8F8FFF6F6 + F6FFF6F6F6FFF6F6F6FFD2E4EAFF49B3C4FF79E6F7FF3F9DADFFB5D4DAFFF8F8 + F8FF6A6A6A6A6A6A6A006A6A6A0058585800616161006161616BF4F4F4FFF0F0 + F0FFF0F0F0FFF0F0F0FF79AFC1FFD9F4FFFF3E9BACFFB0CFD5FFF0F0F0FFF4F4 + F4FF6161616B61616100585858004C4C4C00515151005656566CEFEFEFFFEAEA + EAFFEAEAEAFFEAEAEAFF000000FF4F8393FFB2C6CCFFEAEAEAFFEAEAEAFFEFEF + EFFF5656566C515151004C4C4C004B4B4B534C4C4C6E4C4C4C6EEBEBEBFFE4E4 + E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFEBEB + EBFF4C4C4C6E4C4C4C6E4B4B4B533C3C3C70F0F0F0FFF0F0F0FFECECECFFE8E8 + E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFECEC + ECFFF0F0F0FFF0F0F0FF3C3C3C701B1B1B581717177517171775171717751717 + 1775171717751717177517171775171717751717177517171775171717751717 + 177517171775171717751B1B1B58FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00777777607777 + 77CF747474FF707070EF6B6B6B7F656565AF606060EF5959599F53535310FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF007373 + 737F696969FF6A6A6ABFFFFFFF00FFFFFF005858589F545454FF4A4A4ACFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006D6D + 6D7F656565FF636363BFFFFFFF00FFFFFF004F4F4F7F4E4E4EFF414141FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006767 + 677F5F5F5FFF5B5B5BBFFFFFFF004D4D4D10464646DF464646FF3838389FFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006060 + 607F595959FF535353DF4C4C4C7F454545CF444444FF363636BFFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005858 + 587F535353FF4A4A4ABFFFFFFF00FFFFFF003434349F383838FF262626CF1F1F + 1F10FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004F4F + 4F7F4D4D4DFF414141BFFFFFFF00FFFFFF002B2B2B10262626FF2D2D2DFF1717 + 1770FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004646 + 467F464646FF383838BFFFFFFF00FFFFFF00FFFFFF001C1C1CFF292929FF1010 + 107FFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003D3D + 3D7F404040FF2F2F2FCFFFFFFF00FFFFFF001B1B1B70242424FF0F0F0FEF0A0A + 0A20FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003C3C3C603434 + 34AF2D2D2DBF262626BF1F1F1F8F1919198F131313BF0D0D0D8F09090920FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF006B6B6B80656565F0606060FF595959F0535353C0FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF005E5E5EE0595959FF51515160FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF005C5C5C30575757FF4F4F4FF0FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0054545490525252FF464646A0FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF004C4C4CE0494949FF3D3D3D50FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF004A4A4A30454545FF3C3C3CF0FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0041414190444444FF323232A0FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00383838E0383838FF2A2A2A50FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0036363640353535FF282828FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003434 + 34802D2D2DC0262626C01F1F1FC0191919B0FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00777777607777 + 77EF777777FF7575758FFFFFFF00FFFFFF00FFFFFF00616161AF5B5B5BFF5454 + 5470FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF007777 + 77BF747474FFFFFFFF00FFFFFF00FFFFFF00FFFFFF0059595910535353CFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF007373 + 73BF6E6E6EFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004A4A4ABFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006D6D + 6DBF686868FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00414141BFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006767 + 67BF616161FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00383838BFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006060 + 60BF595959FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF002F2F2FBFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005858 + 58BF515151FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00262626BFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004F4F + 4F8F4B4B4BFF41414150FFFFFF00FFFFFF00FFFFFF00242424401E1E1E8FFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004646 + 46203F3F3FEF383838CF31313120FFFFFF00232323401C1C1CCF16161620FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00363636202F2F2F9F282828BF212121BF1B1B1B8F14141430FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF002B2B + 2BFF242424FF1E1E1EFF171717FF121212FF0C0C0CFF070707FF030303FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0074747411707070996B6B6B666565657760606099595959BBFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF006E6E6EEE6A6A6A77FFFFFF00FFFFFF0058585877515151FFFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006D6D + 6D66666666FF63636388FFFFFF00FFFFFF00FFFFFF00484848BBFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006767 + 6744606060FF5B5B5BFF545454994D4D4D33FFFFFF003F3F3F44FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00595959BB555555FF515151FF484848FF3D3D3DCC36363644FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0077777775777777FF777777FF7777 + 77FF777777FF777777FF5F5F5FFF3C3C3CFF181818FF000000FF000000FF0000 + 00FF000000FF00000074FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004F4F + 4F11FFFFFF00FFFFFF00FFFFFF00323232662B2B2BDD323232FF1E1E1ECCFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004646 + 46663F3F3F77FFFFFF00FFFFFF00FFFFFF00FFFFFF001C1C1CFF161616DDFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003D3D + 3D66373737FF2F2F2F11FFFFFF00FFFFFF00FFFFFF00141414EE0F0F0F77FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003434 + 34662D2D2DEE262626CC1F1F1F7719191966131313770D0D0D88FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00767676FF747474FF7070 + 70FF6C6C6CFF686868FF636363FF5E5E5EFF595959FF535353FF4E4E4EFF4848 + 48FF424242FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006F6F6FFF6B6B6BFF6666 + 66FF616161FF5C5C5CFF575757FF515151FF4B4B4BFF454545FFFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00646464FF5F5F5FFF5A5A + 5AFF545454FF4F4F4FFF494949FF434343FF3D3D3DFF373737FF313131FF2B2B + 2BFF252525FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00585858FF525252FF4C4C + 4CFF464646FF404040FF3A3A3AFF343434FF2E2E2EFF282828FFFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004A4A4AFF444444FF3E3E + 3EFF383838FF323232FF2C2C2CFF262626FF202020FF1B1B1BFF161616FF1111 + 11FF0C0C0CFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003C3C3CFF353535FF2F2F + 2FFF292929FF242424FF1E1E1EFF191919FF141414FF0F0F0FFFFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00767676FF747474FF7070 + 70FF6C6C6CFF686868FF636363FF5E5E5EFF595959FF535353FF4E4E4EFF4848 + 48FF424242FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006B6B6B6B6666 + 66FF616161FF5C5C5CFF575757FF515151FF4B4B4BFF454545FF3F3F3FFF3939 + 396BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00646464FF5F5F5FFF5A5A + 5AFF545454FF4F4F4FFF494949FF434343FF3D3D3DFF373737FF313131FF2B2B + 2BFF252525FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005252526B4C4C + 4CFF464646FF404040FF3A3A3AFF343434FF2E2E2EFF282828FF232323FF1D1D + 1D6BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004A4A4AFF444444FF3E3E + 3EFF383838FF323232FF2C2C2CFF262626FF202020FF1B1B1BFF161616FF1111 + 11FF0C0C0CFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003535356B2F2F + 2FFF292929FF242424FF1E1E1EFF191919FF141414FF0F0F0FFF0B0B0BFF0707 + 076BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00767676FF747474FF7070 + 70FF6C6C6CFF686868FF636363FF5E5E5EFF595959FF535353FF4E4E4EFF4848 + 48FF424242FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00616161FF5C5C5CFF575757FF515151FF4B4B4BFF454545FF3F3F3FFF3939 + 39FF333333FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00646464FF5F5F5FFF5A5A + 5AFF545454FF4F4F4FFF494949FF434343FF3D3D3DFF373737FF313131FF2B2B + 2BFF252525FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00464646FF404040FF3A3A3AFF343434FF2E2E2EFF282828FF232323FF1D1D + 1DFF181818FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004A4A4AFF444444FF3E3E + 3EFF383838FF323232FF2C2C2CFF262626FF202020FF1B1B1BFF161616FF1111 + 11FF0C0C0CFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00292929FF242424FF1E1E1EFF191919FF141414FF0F0F0FFF0B0B0BFF0707 + 07FF030303FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00757575FF737373FF6F6F + 6FFF6B6B6BFF676767FF626262FF5D5D5DFF585858FF525252FF4D4D4DFF4747 + 47FF414141FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006E6E6EFF6A6A6AFF6565 + 65FF606060FF5B5B5BFF565656FF505050FF4A4A4AFF444444FF3E3E3EFF3838 + 38FF323232FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00636363005E5E5E005959 + 5900535353004E4E4E0048484800424242003C3C3C0036363600303030002A2A + 2A0024242400FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0057575700515151004B4B + 4B00454545003F3F3F0039393900333333002D2D2D0027272700222222001C1C + 1C0017171700FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0049494900434343003D3D + 3D0037373700313131002B2B2B00252525001F1F1F001A1A1A00151515001111 + 11000C0C0C00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003B3B3B00343434002E2E + 2E0028282800232323001D1D1D0018181800131313000F0F0F000B0B0B000707 + 070003030300FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0075757500737373006F6F + 6F006B6B6B0067676700626262005D5D5D0058585800525252004D4D4D004747 + 470041414100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006E6E6E006A6A6A006565 + 6500606060005B5B5B0056565600505050004A4A4A00444444003E3E3E003838 + 380032323200FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00636363FF5E5E5EFF5959 + 59FF535353FF4E4E4EFF484848FF424242FF3C3C3CFF363636FF303030FF2A2A + 2AFF242424FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00575757FF515151FF4B4B + 4BFF454545FF3F3F3FFF393939FF333333FF2D2D2DFF272727FF222222FF1C1C + 1CFF171717FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0049494900434343003D3D + 3D0037373700313131002B2B2B00252525001F1F1F001A1A1A00151515001111 + 11000C0C0C00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003B3B3B00343434002E2E + 2E0028282800232323001D1D1D0018181800131313000F0F0F000B0B0B000707 + 070003030300FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0075757500737373006F6F + 6F006B6B6B0067676700626262005D5D5D0058585800525252004D4D4D004747 + 470041414100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006E6E6E006A6A6A006565 + 6500606060005B5B5B0056565600505050004A4A4A00444444003E3E3E003838 + 380032323200FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00636363005E5E5E005959 + 5900535353004E4E4E0048484800424242003C3C3C0036363600303030002A2A + 2A0024242400FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0057575700515151004B4B + 4B00454545003F3F3F0039393900333333002D2D2D0027272700222222001C1C + 1C0017171700FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00494949FF434343FF3D3D + 3DFF373737FF313131FF2B2B2BFF252525FF1F1F1FFF1A1A1AFF151515FF1111 + 11FF0C0C0CFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003B3B3BFF343434FF2E2E + 2EFF282828FF232323FF1D1D1DFF181818FF131313FF0F0F0FFF0B0B0BFF0707 + 07FF030303FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00D8874040D88B4385DA8E4994D989438FD8844090D884419AD373 + 3A8ACC62320DC95B2E01FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00D7833E53E2A76CDEE9BC91FFE7BA8FFFE7B78BFFE2A471FBD67E + 42B6CB5C2F0AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00D67D3B1CDD9656BAE3A973F2E1A873F5E1A471F7D3773E98CB5F + 3008FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00D4793C77E2A670F7DA8847ADD67E43A0E4AE82FFCF6D3A99FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00D1713822DE9B63E2DC965EDFCF693554CF693580E2A97CFFD16C3AA5FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00D06A + 3503D78042AADF9F6AF7CD663466C95D2F0ACC613388E1A679FFD57A44D2C24A + 2706FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CF6A + 365CDF9D68F6DA8B52D1CB5F314EC7592E2ACD6737A0E1A67AFFD88653F2BF46 + 250DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CC633215DB93 + 5EEAE2A779FFD8834AD3CF6A3AB2CE6839B5D57A45D8E3A881FFD98656F9BE41 + 231BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CB5D3001D3743F9BE2A9 + 7CFFCC663799FFFFFF00FFFFFF00FFFFFF00CC6337B1DFA077FFDA895AFFBB3E + 2222FFFFFF00FFFFFF00FFFFFF00FFFFFF00CA5C2F0ACB5F3044E1A475FFDA8C + 58ECC6522C3DFFFFFF00FFFFFF00BF452413C348277FDC966BFFDB8F60FFBD3F + 2154B6381E02FFFFFF00FFFFFF00FFFFFF00CE6838AEDA8F5DFEDB9060FFD783 + 50EDC4502B8DBD422310BC3F222AC34D2BA2D07142EAD67E51FFD57C4DFFC655 + 31BDB6391D31FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101000101 + 0100010101000101012B010101AC0101012B010101000101012B010101AC0101 + 012BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101000101 + 01000101010001010160010101A6010101000101010001010160010101A60101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101000101 + 010001010100010101A9010101620101010001010100010101A9010101620101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000101012E0101 + 01B5010101B5010101B5010101B5010101B5010101B5010101B5010101B50101 + 01B5FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101000101 + 010001010166010101B1010101000101010001010166010101B1010101000101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101000101 + 0100010101B5010101690101010001010100010101B501010169010101000101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101C30101 + 01C3010101C3010101C3010101C3010101C3010101C3010101C3010101C30101 + 0131FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101000101 + 016F010101BE01010100010101000101016F010101BE01010100010101000101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101000101 + 01C7010101730101010001010100010101C70101017301010100010101000101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000003A0000 + 00E400000039000000000000003A000000E40000003900000000010101000101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101560101 + 01AC010101560101010001010100010101410101019601010100010101000101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000101012C010101AF0101 + 0100010101AF0101012C010101000101019A0101014201010100010101000101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000101012D010101B40101 + 0100010101B40101012D010101440101019D0101010001010100010101000101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101000101015D0101 + 01B90101015D01010100010101A2010101460101010001010100010101000101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 01000101010001010148010101A70101010001010160010101BF010101600101 + 0100FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 010001010100010101AD0101014A01010132010101C501010100010101C50101 + 0132FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 01000101014E010101B30101010001010133010101CC01010100010101CC0101 + 0133FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000000000000000000 + 0000000000C600000054000000000000000000000070000000E1000000700000 + 0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF001FD1F9241ECFF8E41ECEF7FC1CCCF6FF1CCAF5F81BC8F4CE1BC6F44FFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF001ECFF7F3A2E7FBFFD3F6FFFFC7F4FFFFBBF1FFFFA2E9FBFF1AC3F2DCFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF001CCCF6FFD6F7FFFFBCEFFFFFABEBFFFF9AE6FFFFA7EDFDFF18BFF0FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF001CC9F4FFBAF0FDFFAAEAFEFFA2E9FEFF79DDFBFF7BDFFBFF17BBEDFFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF001BC6F3FF87E2FAFF40CBF5FF34C4F3FF25BAF1FF5CCDF6FF17B7EBFFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0019C3F1FFA2E9FCFF69D9FAFF51D2F9FF3EC9F7FF5ACCF5FF15B3E8FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF001ECEF80E1DCCF7E41BCAF6FC1BC8F5FF1AC5 + F4F81AC2F2FF79DCF8FF3CC7F4FF30BFF3FF23B5F0FF6CD7F9FF14AFE5FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF001CCBF68891E1FAFFDFF8FFFFD7F7FFFFCCF4 + FFFFA9E9FAFF2AC2F0FF64D6F9FF4CCFF8FF3BC6F6FF68D6F9FF14AAE2FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF001BC8F4FFDAF7FEFFD1F4FFFFC3F1FFFFB7EE + FFFFBFF2FEFF17B7EBFF3AC4F3FF2DBBF2FF20B0EFFF51C7F4FF12A5DFFFFFFF + FF00FFFFFF00FFFFFF00FFFFFF001BC4F1FFCFF5FEFFC3F0FEFFBDEFFEFFA2E7 + FCFF99E8FCFF15B3E7FF5ED3F9FF48CCF8FF36C2F5FF61D3F8FF12A1DCFFFFFF + FF00FFFFFF00FFFFFF00FFFFFF0019C0EFFFAAEAFBFF78DAF8FF61D4F6FF44CD + F5FF66DBF8FF14ADE4FF36C1F2FF2BB7F1FF1AB1F2FF1BB7F4FF14B3F1FF13AF + F0FF13ACEDF811A8EACE11A5E84F18BBECFFBDEFFCFF99E3FBFF89DFFAFF74D9 + F9FF63DAF8FF13A8E0FF5BD2F9FF44C9F7FF16B5F1FFC2F0FDFFCEF4FFFFC6F4 + FFFFB8EFFEFF89E0F6FF109EE2DC16B7E9FFBFF1FDFF74D9F7FF5BD1F6FF44CB + F5FF8EE6FCFF12A2DCFF47C7F4FF2EB6F1FF13AFEEFFD6F7FFFFBDEFFFFFABEB + FFFF9FE7FFFFAEF0FEFF0F98DCFF16B2E6A98EDDF4FF9EE6FCFF85DEFAFF7BDD + FAFF6CD3F2FF24A9DFFF61D1F1FF72DEF9FF2CB6ECFF7EDAF5FFB5EEFEFFA7EB + FEFF8FE3FBFF58CFF1FF0E91D6A914ADE2705FCBEDFF8AE0F6FF88E3F9FF6FDA + F4FF47C1E6FF1099D5BC1097D4CC0F93D3F91099D9E24AC3ECFF72DAF5FF71DE + F7FF57D3F3FF39B8E5FF0D8AD17013A8DE0013A4DC8711A1DACC119ED7F9119A + D5CC1097D3871094D121FFFFFF00FFFFFF00109CDE210F98DA870E93D7CC0E8F + D4F90D8BD1CC0D89CE870D85CC21FFFFFF000101E4000101AC00000000370000 + 005F000000370101AC000101E5000101E5000101AC00000000370000005F0000 + 00370101AC000101E400FFFFFF00FFFFFF000101E4820101E4AC000095CCD6D6 + D6FF000095CC0101E4AC0101E4AC0101E4AC0101E4AC000095CCD6D6D6FF0000 + 95CC0101E4AC0101E482FFFFFF00FFFFFF000101DDB28383FFFF3D3DD5FFB1B1 + B1FF3D3DD5FF7E7EFFFF7E7EFFFF7E7EFFFF7E7EFFFF3D3DD5FFB1B1B1FF3D3D + D5FF8383FFFF0101DDB2FFFFFF00FFFFFF000101D5B97777FDFF2F2FC1FF1111 + 88FF2F2FC1FF6E6EFBFF6E6EFBFF6E6EFBFF6E6EFBFF2F2FC1FF111188FF2F2F + C1FF7777FDFF0101D5B9FFFFFF00FFFFFF000000CBC26D6DFBFFD7D7FBFFA1A1 + ECFFA8A8F1FFC4C4E8FF6464F5FF6464F5FF6464F5FF5C5CEFFF4E4EE4FF5C5C + EFFF6D6DFBFF0000CBC2FFFFFF00FFFFFF000000C3C96363F8FF4646DEFF5050 + E7FF5050E7FF4646DEFF5A5AF0FF5A5AF0FF5A5AF0FF5A5AF0FF5A5AF0FF5A5A + F0FF6363F8FF0000C3C9FFFFFF00FFFFFF0000002872FFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF00002872FFFFFF00FFFFFF0000002775FEFEFDFFFDFDFBFFFDFD + FBFFFDFDFBFFFDFDFBFFFDFDFBFFFDFDFBFFFDFDFBFFFDFDFBFFFDFDFBFFFDFD + FBFFFEFEFDFF00002775FFFFFF00FFFFFF0000002678FDFDF9FFFAFAF7FFFAFA + F7FFFAFAF7FFFAFAF7FFFAFAF7FFFAFAF7FFFAFAF7FFFAFAF7FFFAFAF7FFFAFA + F7FFFDFDF9FF00002678FFFFFF00FFFFFF000000267BFBFBF5FFF7F7F1FFF7F7 + F1FFF7F7F1FFF7F7F1FFF7F7F1FFF7F7F1FFF7F7F1FFF7F7F1FFF7F7F1FFF7F7 + F1FFFBFBF5FF0000267BFFFFFF00FFFFFF000000257FFAFAF1FFF3F3EBFFF3F3 + EBFFF3F3EBFFF3F3EBFFF3F3EBFFF3F3EBFFF3F3EBFFF3F3EBFFF3F3EBFFF3F3 + EBFFFAFAF1FF0000257FFFFFFF00FFFFFF0000002482F8F8EDFFEFEFE6FFEFEF + E6FFEFEFE6FFEFEFE6FFEFEFE6FFEFEFE6FFEFEFE6FFEFEFE6FFEFEFE6FFEFEF + E6FFF8F8EDFF00002482FFFFFF00FFFFFF0000002386F6F6E9FFECECE0FFECEC + E0FFECECE0FFECECE0FFECECE0FFECECE0FFECECE0FFECECE0FFECECE0FFECEC + E0FFF6F6E9FF00002386FFFFFF00FFFFFF000101228DF5F5E6FFE9E9DAFFE9E9 + DAFFE9E9DAFFE9E9DAFFE9E9DAFFE9E9DAFFE9E9DAFFE9E9DAFFE9E9DAFFE9E9 + DAFFF5F5E6FF0101228DFFFFFF00FFFFFF0001011F9AF9F9E9FFF3F3E3FFF3F3 + E3FFF3F3E3FFF3F3E3FFF3F3E3FFF3F3E3FFF3F3E3FFF3F3E3FFF3F3E3FFF3F3 + E3FFF9F9E9FF01011F9AFFFFFF00FFFFFF0001011D7C01011DA501011DA50101 + 1DA501011DA501011DA501011DA501011DA501011DA501011DA501011DA50101 + 1DA501011DA501011D7CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004E4E4E0050505000535353005454 + 540D5555553755555553555555625555556255555553555555375454540D5353 + 5300505050004E4E4E00FFFFFF00FFFFFF004E4E4E0050505000535353286262 + 60699F9F96AAD7D7CCDFECECE5F8ECECE5F8D7D7CCDF9F9F96AA626260695353 + 5328505050004E4E4E00FFFFFF00FFFFFF004E4E4E005050502868686578CECE + BFE3E7E7DBFFF1F1EBFFC1C1BEFFF1F1EBFFF1F1EBFFE7E7DBFFCECEBFE36969 + 6678505050284E4E4E00FFFFFF00FFFFFF004D4D4D0E5D5D5B6CCDCDBFE3E0E0 + D0FFF0F0E9FFF1F1EBFF8C8C8CFFF1F1EBFFF1F1EBFFF0F0E9FFE0E0D0FFCFCF + C2E35E5E5C6C4D4D4D0EFFFFFF00FFFFFF004A4A4A3A9A9A90ACDDDDCCFFE6E6 + DAFFF1F1EBFFF1F1EBFF848484FFF1F1EBFFF1F1EBFFF1F1EBFFE6E6DAFFDFDF + CEFF9D9D96AC4A4A4A3AFFFFFF00FFFFFF004646465ACBCBBDE1DDDDCCFFDDDD + CCFFDDDDCCFFDDDDCCFF5C5C5CFFDDDDCCFFDDDDCCFFDDDDCCFFDDDDCCFFDDDD + CCFFD2D2C7E14646465AFFFFFF00FFFFFF004242426BDBDBCCF8DDDDCCFFDDDD + CCFFF1F1EBFFF1F1EBFF4F4F4FFFF1F1EBFFF1F1EBFFF1F1EBFFEFEFE7FFDDDD + CCFFE2E2D6F84242426BFFFFFF00FFFFFF003E3E3E6DDDDDCEF8DDDDCCFFF1F1 + EBFFF1F1EBFF353535FF777777FF484848FF555555FF626262FF6E6E6EFFA9A9 + A0FFE5E5D9F83E3E3E6DFFFFFF00FFFFFF003A3A3A5ECECEC2E2DDDDCCFFF1F1 + EBFFF1F1EBFFDFDFDCFF383838FFDFDFDCFFDFDFDCFFDFDFDCFFDFDFDBFFD9D9 + CCFFD7D7CFE23A3A3A5EFFFFFF00FFFFFF003535353F94948EB3E0E0D0FFEFEF + E7FFF1F1EBFFF1F1EBFFDFDFDCFFF1F1EBFFF1F1EBFFF1F1EBFFEFEFE7FFE2E2 + D3FF9B9B99B33535353FFFFFFF00FFFFFF003232321044444377D4D4CAE6EDED + E4FFF1F1EBFFF1F1EBFFF1F1EBFFF1F1EBFFF1F1EBFFF1F1EBFFEDEDE5FFDADA + D5E64545457732323210FFFFFF00FFFFFF00303030002C2C2C2F4B4B4A89DADA + D5E6F3F3EEFFF1F1EBFFF1F1EBFFF1F1EBFFF1F1EBFFF3F3EEFFDEDEDBE64C4C + 4C892C2C2C2F30303000FFFFFF00FFFFFF00303030002A2A2A001C1C1C322F2F + 2F818D8D8CBBD9D9D7E6F3F3EFF9F3F3F0F9DADAD8E68E8E8EBB303030811C1C + 1C322A2A2A0030303000FFFFFF00FFFFFF00303030002A2A2A001A1A1A000F0F + 0F120C0C0C4A0C0C0C720C0C0C860C0C0C860C0C0C720C0C0C4A0F0F0F121A1A + 1A002A2A2A0030303000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 01000101013E010101AF010101B00101013E010101000101013F010101B40101 + 01B601010140FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 0112010101AF0101012C01010135010101B301010112010101B50101012E0101 + 0138010101B9FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 0112010101B10101010001010112010101B401010112010101B7010101000101 + 0113010101BBFFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 0112010101B20101010001010112010101B601010113010101B9010101000101 + 0113010101BEFFFFFF00FFFFFF00FFFFFF00FFFFFF00010101B1010101590101 + 0112010101B40101012E01010137010101B801010113010101BB0101012F0101 + 013A010101C0FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101B20101015A0101 + 010001010140010101B8010101B9010101410101010001010143010101BF0101 + 01C101010144FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101002C120A00AF45 + 230033150D000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815F00B9543200AF45 + 2300D4573500A8462D0039181000010101000101010001010145010101C60101 + 01C801010147FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815F00BC573500AF45 + 23FFD4573540DF5D3B00702F1E000101010001010114010101C7010101320101 + 013D010101CDFFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815FFFBE5A38FFAF45 + 23E0D45735FFDF5D3B00391810000101010001010114010101CA010101000000 + 0015000000D5FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815F00BC573500AF45 + 23FFD457354039181000010101000101010001010115010101CC010101000000 + 0016000000DEFFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815F00B9543200AF45 + 23009D40270001010100010101CA0101016600000015000000D5000000370000 + 0045000000E6FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815F00B9543200AF45 + 230033150D0001010100010101CC00000068000000000000004E000000E40000 + 00E900000053FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815F00BE5A3800B34B + 2900D4573500DF5D3B00702F1E0001010100010101000101013F010101B40101 + 01B601010140FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815F40BE5A38FFB148 + 2600D4573500DF5D3B00702F1E000101010001010112010101B50101012E0101 + 0138010101B9FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815FFFBE5A38E0AF45 + 23FFD45735FFDF5D3B00391810000101010001010112010101B7010101000101 + 0113010101BBFFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815F40BE5A38FFB148 + 2600D457350039181000010101000101010001010113010101B9010101000101 + 0113010101BEFFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815F00BE5A3800B34B + 29009D40270001010100010101B70101015C01010113010101BB0101012F0101 + 013A010101C0FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815F00BE5A3800873A + 21000101010001010100010101B90101015D0101010001010143010101BF0101 + 01C101010144FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7815F00BE5A38002E15 + 0D00010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 010001010143010101BE010101C0010101440101010001010145010101C60101 + 01C801010147FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 0113010101BF010101300101013B010101C401010114010101C7010101320101 + 013D010101CDFFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 0113010101C10101010001010114010101C601010114010101CA010101000000 + 0015000000D5FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010100010101000101 + 0114010101C40101010001010114010101C901010115010101CC010101000000 + 0016000000DEFFFFFF00FFFFFF00FFFFFF00FFFFFF00010101C1010101610101 + 0114010101C6010101320101013D010101CB00000015000000D5000000370000 + 0045000000E6FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101C4010101630101 + 010001010146010101CB010101CC00000048000000000000004E000000E40000 + 00E900000053FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006B6FFEFF6B6FFEFF6B6F + FEFFFFFFFF0073AAFFFF73AAFFFF73AAFFFFFFFFFF0067D5F0FF67D5F0FF67D5 + F0FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006B6FFEFF6B6FFEFF6B6F + FEFFFFFFFF0073AAFFFF73AAFFFF73AAFFFFFFFFFF0067D5F0FF67D5F0FF67D5 + F0FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006B6FFEFF6B6FFEFF6B6F + FEFFFFFFFF0073AAFFFF73AAFFFF73AAFFFFFFFFFF0067D5F0FF67D5F0FF67D5 + F0FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B2EBD0FFB2EBD0FFB2EB + D0FFFFFFFF006DCC50FF6DCC50FF6DCC50FFFFFFFF00EBB060FFEBB060FFEBB0 + 60FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B2EBD0FFB2EBD0FFB2EB + D0FFFFFFFF006DCC50FF6DCC50FF6DCC50FFFFFFFF00EBB060FFEBB060FFEBB0 + 60FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B2EBD0FFB2EBD0FFB2EB + D0FFFFFFFF006DCC50FF6DCC50FF6DCC50FFFFFFFF00EBB060FFEBB060FFEBB0 + 60FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B07A58FFB07A58FFB07A + 58FFFFFFFF00DD9BD9FFDD9BD9FFDD9BD9FFFFFFFF00B177FFFFB177FFFFB177 + FFFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B07A58FFB07A58FFB07A + 58FFFFFFFF00DD9BD9FFDD9BD9FFDD9BD9FFFFFFFF00B177FFFFB177FFFFB177 + FFFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B07A58FFB07A58FFB07A + 58FFFFFFFF00DD9BD9FFDD9BD9FFDD9BD9FFFFFFFF00B177FFFFB177FFFFB177 + FFFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF007F7F554D7F7F55667F7F55667F7F55667F7F + 55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F55667F7F + 55667F7F55667F7F55667F7F554D7D7D5367FFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF7D7D53677A7A5168FFFFFEFFFFCC44FFFECB43FFFDCA + 42FFFCC941FFFAC73FFFF8C53DFFF6C33CFFF5C23AFFF3C038FFF1BE36FFF0BD + 35FFEFBC34FFFFFFFEFF7A7A516877774E6AFEFEFCFFFFCC44FFFFEE88FFFDCA + 42FFFCEB85FFFBEA84FFF8C53DFFF6E57FFFF4E37DFFF3C038FFF1E07AFFEFDE + 78FFEFBC34FFFEFEFCFF77774E6A73734B6BFDFDF9FFFFCC44FFFECB43FFF5CE + 64FFEBD285FFE9D083FFE7CE81FFE5CC80FFE4CB7EFFE2C97CFFE0C77AFFDFC6 + 79FFDEC578FFFDFDF9FF73734B6B6F6F476DFCFCF7FFFFCC44FFFFEE88FFECD2 + 86FFFCFCFAFFFCFCFAFFD6D6C5FFFCFCFAFFFCFCFAFFD1D1C0FFFCFCFAFFFCFC + FAFFCDCDBCFFFCFCF7FF6F6F476D6B6B446EFBFBF4FFFFCC44FFFECB43FFECD2 + 86FFDADAC9FFD8D8C7FFE98361FFE98361FFE98361FFE98361FFE98361FFE983 + 61FFE98361FFFBFBF4FF6B6B446E67674070F9F9F1FFFFCC44FFFFEE88FFECD2 + 86FFF9F9F5FFF9F9F5FFC86442FFF9F9F5FFF9F9F5FFD1D1C0FFF9F9F5FFF9F9 + F5FFC86442FFF9F9F1FF6767407063633C72F8F8EEFFFFCC44FFFECB43FFECD2 + 86FFDADAC9FFD8D8C7FFAD4826FFD4D4C3FFD3D3C2FFD9D9CAFFCFCFBEFFCECE + BDFFAD4826FFF8F8EEFF63633C725E5E3873F7F7EBFFFFCC44FFFFEE88FFECD2 + 86FFF7F7F1FFF7F7F1FFB84927FFF7F7F1FFF7F7F1FFD1D1C0FFF7F7F1FFF7F7 + F1FFB84927FFF7F7EBFF5E5E38735A5A3475F6F6E9FFFFCC44FFFECB43FFECD2 + 86FFDADAC9FFD8D8C7FFDA5B39FFDA5B39FFDA5B39FFDA5B39FFDA5B39FFDA5B + 39FFDA5B39FFF6F6E9FF5A5A347555553077F5F5E6FFFFCC44FFFFEE88FFECD2 + 86FFF5F5EEFFF5F5EEFFD6D6C5FFF5F5EEFFF5F5EEFFD1D1C0FFF5F5EEFFF5F5 + EEFFCDCDBCFFF5F5E6FF555530774D4D297AF4F4E4FFFFCC44FFFECB43FFECD2 + 86FFDADAC9FFD8D8C7FFD6D6C5FFD4D4C3FFD3D3C2FFD1D1C0FFCFCFBEFFCECE + BDFFCDCDBCFFF4F4E4FF4D4D297A3A3A1881F9F9E9FFF3F3E2FFF3F3E2FFF3F3 + E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3E2FFF3F3 + E2FFF3F3E2FFF9F9E9FF3A3A18812D2D0D652B2B0B872B2B0B872B2B0B872B2B + 0B872B2B0B872B2B0B872B2B0B872B2B0B872B2B0B872B2B0B872B2B0B872B2B + 0B872B2B0B872B2B0B872D2D0D65FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00CC812900D58A3000DD923600E4993B00E99E + 3F48E99E3F99E89D3E00E89D3E00DB903500DB903500DB903500DB903500E297 + 3A00E79C3E00E99E3F99FFFFFF00CC812900D58A3000DD923600E3983B48E499 + 3BCCE4993BCCE4993B00DB903400DB903500DB903500DB903500DB903500DF94 + 3700E3983B7AE4993BCCFFFFFF00CC812900D58A3000DC913648DD9236CCFFE5 + 99FFDD9236CCD98E3300D78C3100DB903504DB903511DB903528DB903547DD92 + 368DE4A148CDDD9236B6FFFFFF00CC812900D4892F48D58A30CCFFE599FFFCD7 + 8BFFD58A30CCD58A30CCD58A30CCD68C32CDDA933BD1DF9E47D7E6AC57E0F3C2 + 73F1EDB968EBD58A308DFFFFFF00CB802848CC8129CCFFE397FFF4BE72FFF6C6 + 7AFFF8CE82FFF8CD81FFF8CC80FFF7CB7FFFF7C87CFFF6C478FFF5C074FFF3C1 + 74FCD48F3AD3CD822A35FFFFFF00C27722CCFDDF93FFEFB468FFEFB468FFEFB4 + 68FFEFB468FFEBB061FFE3A754FFDA9E49FFD59843FFD29541FFD69D4AFCCC8B + 38DDC2772279C67B2500FFFFFF00BA6F1C48B96E1BCCFAD68AFFEEB266FFF1B8 + 67FFF0B956FFECB240FFEBAF3BFFEAAD38FFE5A736F9D89833ECC17A23D3B96E + 1B79BD731E0ABF752000FFFFFF00B96E1B00B0651548AF6414CCFACC6CFFFCBD + 2CFFAF6414CCAF6414CCAF6414CCAF6414CBAF6414B6AF64148DB0651535B66B + 1900BD731E00BF752000FFFFFF00B96E1B00AF641400A75C0E48A65B0DCCFFC3 + 32FFA65B0DCCAB601100AD621200AD621200AD621200AD621200AF641400B66B + 1900BD731E00BF752000FFFFFF00B96E1B00AF641400A65B0D00A05509489F54 + 08CC9F5408CC9F540800A95E0F00AD621200AD621200AD621200AF641400B66B + 1900BD731E00BF752000FFFFFF00B96E1B00AF641400A65B0D009F5408009A4F + 04489A4F04999A4F04009A4F0400AD621200AD621200AD621200AF641400B66B + 1900BD731E00BF752000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0003030360030303BE03030360FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00030303C1030303C1030303C1FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0003030395030303C6030303C6FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF000303030002020266020202CCFFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0002020200020202B802020283FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0001010172010101E00101011CFFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000004D0000000D000000670000 + 000D000000670000000D000000670000000D000000670000000D000000670000 + 000D0000004DFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000D000000000000000000000000000000000000 + 00000000000DFFFFFF00FFFFFF00FFFFFF000000006B00000000000000000000 + 000000000000000000000000006B000000000000000000000000000000000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000E000000000000000000000000000000000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 0000000000000000000000000071000000000000000000000000000000000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000000 + 000000000000000000000000000F000000000000000000000000000000000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF00000000780000000F000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780000 + 000F00000078FFFFFF00FFFFFF00FFFFFF000000001000000000000000000000 + 0000000000000000000000000010000000000000000000000000000000000000 + 000000000010FFFFFF00FFFFFF00FFFFFF000000008000000000000000000000 + 0000000000000000000000000080000000000000000000000000000000000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000010101000101 + 0100010101000000000000000011000000000101010001010100010101000000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101018901010100010101000101 + 0100010101000101010001010189010101000101010001010100010101000101 + 010001010189FFFFFF00FFFFFF00FFFFFF000101011401010100010101000101 + 0100010101000101010001010113010101000101010001010100010101000101 + 010001010113FFFFFF00FFFFFF00FFFFFF000101017B01010115010101A40101 + 0115010101A401010115010101A401010115010101A401010115010101A40101 + 01150101017BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010181010101AC010101AC0101 + 01AC010101AC010101AC010101AC010101AC010101AC010101AC010101AC0101 + 01AC01010181FFFFFF00FFFFFF00FFFFFF00010101AE010101AE010101AE0101 + 01AE010101AE010101AE010101AE010101AE010101AE010101AE010101AE0101 + 01AE010101AEFFFFFF00FFFFFF00FFFFFF00010101B0010101B0010101000101 + 010001010100010101000000006B010101000101010001010100010101000101 + 01B0010101B0FFFFFF00FFFFFF00FFFFFF00010101B3010101B3010101000101 + 010001010100010101000000000E000000000101010001010100010101000101 + 01B3010101B3FFFFFF00FFFFFF00FFFFFF00010101B6010101B6010101000101 + 0100000000000000000000000071000000000000000001010100010101000101 + 01B6010101B6FFFFFF00FFFFFF00FFFFFF00010101B9010101B9010101000000 + 000000000000000000000000000F000000000000000000000000010101000101 + 01B9010101B9FFFFFF00FFFFFF00FFFFFF00010101BC010101BC000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780101 + 01BC010101BCFFFFFF00FFFFFF00FFFFFF00010101C0010101C0010101000000 + 0000000000000000000000000010000000000000000000000000010101000101 + 01C0010101C0FFFFFF00FFFFFF00FFFFFF00010101C4010101C4010101000101 + 0100000000000000000000000080000000000000000001010100010101000101 + 01C4010101C4FFFFFF00FFFFFF00FFFFFF00010101C7010101C7010101000101 + 0100000000000000000000000011000000000000000001010100010101000101 + 01C7010101C7FFFFFF00FFFFFF00FFFFFF00010101CC010101CC010101000000 + 0000000000000000000001010189000000000000000000000000010101000101 + 01CC010101CCFFFFFF00FFFFFF00FFFFFF00000000D9000000D9000000D90000 + 00D9000000D9000000D9000000D9000000D9000000D9000000D9000000D90000 + 00D9000000D9FFFFFF00FFFFFF00FFFFFF00000000AC000000E6000000E60000 + 00E6000000E6000000E6000000E6000000E6000000E6000000E6000000E60000 + 00E6000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010181010101AC010101AC0101 + 01AC010101AC010101AC010101AC010101AC010101AC010101AC010101AC0101 + 01AC01010181FFFFFF00FFFFFF00FFFFFF00010101AE01010100010101000101 + 010001010100010101000101010D010101000101010001010100010101000101 + 0100010101AEFFFFFF00FFFFFF00FFFFFF00010101B001010100010101000101 + 010001010100000000000000006B000000000101010001010100010101000101 + 0100010101B0FFFFFF00FFFFFF00FFFFFF00010101B301010100010101000101 + 010001010100000000000000000E000000000000000001010100010101000101 + 0100010101B3FFFFFF00FFFFFF00FFFFFF00010101B601010100010101000000 + 0000000000000000000000000071000000000000000000000000010101000101 + 0100010101B6FFFFFF00FFFFFF00FFFFFF00010101B901010100000000000000 + 000000000000000000000000000F000000000000000000000000000000000101 + 0100010101B9FFFFFF00FFFFFF00FFFFFF00010101BC0000000F000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780101 + 010F010101BCFFFFFF00FFFFFF00FFFFFF00010101C001010100000000000000 + 0000000000000000000000000010000000000000000000000000000000000101 + 0100010101C0FFFFFF00FFFFFF00FFFFFF00010101C401010100010101000000 + 0000000000000000000000000080000000000000000000000000010101000101 + 0100010101C4FFFFFF00FFFFFF00FFFFFF00010101C701010100010101000101 + 0100000000000000000000000011000000000000000001010100010101000101 + 0100010101C7FFFFFF00FFFFFF00FFFFFF00010101CC01010100010101000000 + 0000000000000101010001010189010101000000000000000000010101000101 + 0100010101CCFFFFFF00FFFFFF00FFFFFF00000000D900000000000000000000 + 0000000000000000000001010113010101000000000000000000000000000000 + 0000000000D9FFFFFF00FFFFFF00FFFFFF00000000AC000000E6000000E60000 + 00E6000000E6000000E6000000E6000000E6000000E6000000E6000000E60000 + 00E6000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010181010101AC010101AC0101 + 01AC010101AC010101AC010101AC010101AC010101AC010101AC010101AC0101 + 01AC01010181FFFFFF00FFFFFF00FFFFFF00010101AE01010100010101000101 + 01000101010001010100010101AE010101000101010001010100010101000101 + 0100010101AEFFFFFF00FFFFFF00FFFFFF00010101B001010100010101000101 + 01000101010001010100010101B0010101000101010001010100010101000101 + 0100010101B0FFFFFF00FFFFFF00FFFFFF00010101B301010100010101000101 + 01000101010001010100010101B3010101000101010001010100010101000101 + 0100010101B3FFFFFF00FFFFFF00FFFFFF00010101B601010100010101000101 + 01000101010001010100010101B6010101000101010001010100010101000101 + 0100010101B6FFFFFF00FFFFFF00FFFFFF00010101B901010100010101000101 + 01000101010001010100010101B9010101000101010001010100010101000101 + 0100010101B9FFFFFF00FFFFFF00FFFFFF00010101BC010101BC010101BC0101 + 01BC010101BC010101BC0101018E010101BC010101BC010101BC010101BC0101 + 01BC010101BCFFFFFF00FFFFFF00FFFFFF00010101C001010100010101000101 + 01000101010001010100010101C0010101000101010001010100010101000101 + 0100010101C0FFFFFF00FFFFFF00FFFFFF00010101C401010100010101000101 + 01000101010001010100010101C4010101000101010001010100010101000101 + 0100010101C4FFFFFF00FFFFFF00FFFFFF00010101C701010100010101000101 + 01000101010001010100010101C7010101000101010001010100010101000101 + 0100010101C7FFFFFF00FFFFFF00FFFFFF00010101CC01010100010101000000 + 00000101010001010100010101CC010101000101010000000000010101000101 + 0100010101CCFFFFFF00FFFFFF00FFFFFF00000000D900000000000000000000 + 00000000000000000000000000D9000000000000000000000000000000000000 + 0000000000D9FFFFFF00FFFFFF00FFFFFF00000000AC000000E6000000E60000 + 00E6000000E6000000E6000000E6000000E6000000E6000000E6000000E60000 + 00E6000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000004D0000000D000000670000 + 000D000000670101010D010101AC0000000D000000670000000D000000670000 + 000D0000004DFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 00000000000001010100010101AE010101000000000000000000000000000000 + 00000000000DFFFFFF00FFFFFF00FFFFFF000000006B00000000000000000000 + 00000101010001010100010101B0010101000101010000000000000000000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000010101000101 + 01000101010001010100010101B3010101000101010001010100010101000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000010101000101 + 01000101010001010100010101B6010101000101010001010100010101000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000101010F01010100010101000101 + 01000101010001010100010101B9010101000101010001010100010101000101 + 01000101010FFFFFFF00FFFFFF00FFFFFF00010101BC010101BC010101BC0101 + 01BC010101BC010101BC0101018E010101BC010101BC010101BC010101BC0101 + 01BC010101BCFFFFFF00FFFFFF00FFFFFF000101011001010100010101000101 + 01000101010001010100010101C0010101000101010001010100010101000101 + 010001010110FFFFFF00FFFFFF00FFFFFF000000008000000000010101000101 + 01000101010001010100010101C4010101000101010001010100010101000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000010101000101 + 01000101010001010100010101C7010101000101010001010100010101000000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101018901010100010101000101 + 01000101010001010100010101CC010101000101010001010100010101000101 + 010001010189FFFFFF00FFFFFF00FFFFFF000101011401010100010101000101 + 01000101010001010100000000D9010101000101010001010100010101000101 + 010001010113FFFFFF00FFFFFF00FFFFFF000101017B01010115010101A40101 + 0115010101A401010115000000E601010115010101A401010115010101A40101 + 01150101017BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010181010101AC010101AC0101 + 01AC010101AC010101AC010101AC010101AC010101AC010101AC010101AC0101 + 01AC01010181FFFFFF00FFFFFF00FFFFFF000101010E01010100010101000101 + 010001010100010101000101010D010101000101010001010100010101000101 + 01000101010DFFFFFF00FFFFFF00FFFFFF000000006B00000000010101000101 + 010001010100000000000000006B000000000101010001010100010101000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000010101000101 + 010001010100000000000000000E000000000000000001010100010101000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 0000000000000000000000000071000000000000000000000000000000000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000000 + 000000000000000000000000000F000000000000000000000000000000000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF00000000780000000F000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780000 + 000F00000078FFFFFF00FFFFFF00FFFFFF000000001000000000000000000000 + 0000000000000000000000000010000000000000000000000000000000000000 + 000000000010FFFFFF00FFFFFF00FFFFFF000000008000000000000000000000 + 0000000000000000000000000080000000000000000000000000000000000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000010101000101 + 0100010101000000000000000011000000000101010001010100010101000000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101018901010100010101000101 + 0100010101000101010001010189010101000101010001010100010101000101 + 010001010189FFFFFF00FFFFFF00FFFFFF000101011401010100010101000101 + 0100010101000101010001010113010101000101010001010100010101000101 + 010001010113FFFFFF00FFFFFF00FFFFFF000101017B01010115010101A40101 + 0115010101A401010115010101A401010115010101A401010115010101A40101 + 01150101017BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000004D0000000D000000670000 + 000D000000670000000D000000670000000D000000670000000D000000670000 + 000D0000004DFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000D000000000000000000000000000000000000 + 00000000000DFFFFFF00FFFFFF00FFFFFF000000006B00000000000000000000 + 000000000000000000000000006B000000000000000000000000000000000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000E000000000000000000000000000000000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 0000000000000000000000000071000000000000000000000000000000000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000000 + 000000000000000000000000000F000000000000000000000000000000000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF00000000780000000F000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780000 + 000F00000078FFFFFF00FFFFFF00FFFFFF000000001000000000000000000000 + 0000000000000000000000000010000000000000000000000000000000000000 + 000000000010FFFFFF00FFFFFF00FFFFFF000000008000000000000000000000 + 0000000000000000000000000080000000000000000000000000000000000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000000000000000 + 0000000000000000000000000011000000000000000000000000000000000000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101018901010100000000000000 + 0000000000000101010001010189010101000000000000000000000000000101 + 010001010189FFFFFF00FFFFFF00FFFFFF000101011400000000000000000000 + 0000000000000000000001010113010101000000000000000000000000000000 + 000001010113FFFFFF00FFFFFF00FFFFFF00000000AC000000E6000000E60000 + 00E6000000E6000000E6000000E6000000E6000000E6000000E6000000E60000 + 00E6000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000004D0000000D000000670000 + 000D000000670000000D000000670000000D000000670000000D000000670000 + 000D0000004DFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000D000000000000000000000000000000000000 + 00000000000DFFFFFF00FFFFFF00FFFFFF000000006B00000000000000000000 + 000000000000000000000000006B000000000000000000000000000000000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000E000000000000000000000000000000000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 0000000000000000000000000071000000000000000000000000000000000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000000 + 000000000000000000000000000F000000000000000000000000000000000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF00000000780000000F000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780000 + 000F00000078FFFFFF00FFFFFF00FFFFFF000000001000000000000000000000 + 0000000000000000000000000010000000000000000000000000000000000000 + 000000000010FFFFFF00FFFFFF00FFFFFF000000008000000000000000000000 + 0000000000000000000000000080000000000000000000000000000000000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000000000000000 + 0000000000000000000000000011000000000000000000000000000000000000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101018900000000000000000000 + 0000000000000000000001010189000000000000000000000000000000000000 + 000001010189FFFFFF00FFFFFF00FFFFFF00000000D9000000D9000000D90000 + 00D9000000D9000000D9000000D9000000D9000000D9000000D9000000D90000 + 00D9000000D9FFFFFF00FFFFFF00FFFFFF00000000AC000000E6000000E60000 + 00E6000000E6000000E6000000E6000000E6000000E6000000E6000000E60000 + 00E6000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000004D0000000D000000670000 + 000D000000670000000D000000670000000D000000670000000D000000670000 + 000D0000004DFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000D000000000000000000000000000000000000 + 00000000000DFFFFFF00FFFFFF00FFFFFF000000006B00000000000000000000 + 000000000000000000000000006B000000000000000000000000000000000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000E000000000000000000000000000000000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 0000000000000000000000000071000000000000000000000000000000000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000000 + 000000000000000000000000000F000000000000000000000000000000000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF00000000780000000F000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780000 + 000F00000078FFFFFF00FFFFFF00FFFFFF000000001000000000000000000000 + 0000000000000000000000000010000000000000000000000000000000000000 + 000000000010FFFFFF00FFFFFF00FFFFFF000000008000000000010101000101 + 0100010101000000000000000080000000000101010001010100010101000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000101011101010100010101000101 + 0100010101000101010001010111010101000101010001010100010101000101 + 010001010111FFFFFF00FFFFFF00FFFFFF00010101CC010101CC010101CC0101 + 01CC010101CC010101CC010101CC010101CC010101CC010101CC010101CC0101 + 01CC010101CCFFFFFF00FFFFFF00FFFFFF000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000FFFFFF00FFFFFF00FFFFFF00000000AC000000E6000000E60000 + 00E6000000E6000000E6000000E6000000E6000000E6000000E6000000E60000 + 00E6000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010181010101AC010101AC0101 + 01AC010101AC010101AC010101AC010101AC010101AC010101AC010101AC0101 + 01AC01010181FFFFFF00FFFFFF00FFFFFF000101010E01010100010101000101 + 010001010100010101000101010D010101000101010001010100010101000101 + 01000101010DFFFFFF00FFFFFF00FFFFFF000000006B00000000010101000101 + 010001010100000000000000006B000000000101010001010100010101000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000010101000101 + 010001010100000000000000000E000000000000000001010100010101000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 0000000000000000000000000071000000000000000000000000000000000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000000 + 000000000000000000000000000F000000000000000000000000000000000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF00000000780000000F000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780000 + 000F00000078FFFFFF00FFFFFF00FFFFFF000000001000000000000000000000 + 0000000000000000000000000010000000000000000000000000000000000000 + 000000000010FFFFFF00FFFFFF00FFFFFF000000008000000000000000000000 + 0000000000000000000000000080000000000000000000000000000000000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000000000000000 + 0000000000000000000000000011000000000000000000000000000000000000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101018901010100000000000000 + 0000000000000101010001010189010101000000000000000000000000000101 + 010001010189FFFFFF00FFFFFF00FFFFFF000101011400000000000000000000 + 0000000000000000000001010113010101000000000000000000000000000000 + 000001010113FFFFFF00FFFFFF00FFFFFF00000000AC000000E6000000E60000 + 00E6000000E6000000E6000000E6000000E6000000E6000000E6000000E60000 + 00E6000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010181010101AC010101AC0101 + 01AC010101AC010101AC010101AC010101AC010101AC010101AC010101AC0101 + 01AC01010181FFFFFF00FFFFFF00FFFFFF000101010E01010100010101000101 + 010001010100010101000101010D010101000101010001010100010101000101 + 01000101010DFFFFFF00FFFFFF00FFFFFF000000006B00000000010101000101 + 010001010100000000000000006B000000000101010001010100010101000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000010101000101 + 010001010100000000000000000E000000000000000001010100010101000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 0000000000000000000000000071000000000000000000000000000000000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000000 + 000000000000000000000000000F000000000000000000000000000000000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF00000000780000000F000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780000 + 000F00000078FFFFFF00FFFFFF00FFFFFF000000001000000000000000000000 + 0000000000000000000000000010000000000000000000000000000000000000 + 000000000010FFFFFF00FFFFFF00FFFFFF000000008000000000000000000000 + 0000000000000000000000000080000000000000000000000000000000000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000000000000000 + 0000000000000000000000000011000000000000000000000000000000000000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101018900000000000000000000 + 0000000000000000000001010189000000000000000000000000000000000000 + 000001010189FFFFFF00FFFFFF00FFFFFF00000000D9000000D9000000D90000 + 00D9000000D9000000D9000000D9000000D9000000D9000000D9000000D90000 + 00D9000000D9FFFFFF00FFFFFF00FFFFFF00000000AC000000E6000000E60000 + 00E6000000E6000000E6000000E6000000E6000000E6000000E6000000E60000 + 00E6000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010181010101AC010101AC0101 + 01AC010101AC010101AC010101AC010101AC010101AC010101AC010101AC0101 + 01AC01010181FFFFFF00FFFFFF00FFFFFF000101010E01010100010101000101 + 010001010100010101000101010D010101000101010001010100010101000101 + 01000101010DFFFFFF00FFFFFF00FFFFFF000000006B00000000010101000101 + 010001010100000000000000006B000000000101010001010100010101000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000010101000101 + 010001010100000000000000000E000000000000000001010100010101000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 0000000000000000000000000071000000000000000000000000000000000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000000 + 000000000000000000000000000F000000000000000000000000000000000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF00000000780000000F000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780000 + 000F00000078FFFFFF00FFFFFF00FFFFFF000000001000000000000000000000 + 0000000000000000000000000010000000000000000000000000000000000000 + 000000000010FFFFFF00FFFFFF00FFFFFF000000008000000000010101000101 + 0100010101000000000000000080000000000101010001010100010101000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000101011101010100010101000101 + 0100010101000101010001010111010101000101010001010100010101000101 + 010001010111FFFFFF00FFFFFF00FFFFFF00010101CC010101CC010101CC0101 + 01CC010101CC010101CC010101CC010101CC010101CC010101CC010101CC0101 + 01CC010101CCFFFFFF00FFFFFF00FFFFFF000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000FFFFFF00FFFFFF00FFFFFF00000000AC000000E6000000E60000 + 00E6000000E6000000E6000000E6000000E6000000E6000000E6000000E60000 + 00E6000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000004D0000000D000000670000 + 000D000000670000000D000000670000000D000000670000000D000000670000 + 000D0000004DFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000D000000000000000000000000000000000000 + 00000000000DFFFFFF00FFFFFF00FFFFFF000000006B00000000000000000000 + 000000000000000000000000006B000000000000000000000000000000000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000010101000101 + 010001010100000000000000000E000000000101010001010100010101000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000010101000101 + 0100010101000000000000000071000000000101010001010100010101000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000101010F01010100010101000101 + 010001010100010101000101010F010101000101010001010100010101000101 + 01000101010FFFFFFF00FFFFFF00FFFFFF00010101BC010101BC010101BC0101 + 01BC010101BC010101BC010101BC010101BC010101BC010101BC010101BC0101 + 01BC010101BCFFFFFF00FFFFFF00FFFFFF000101011001010100010101000101 + 0100010101000101010001010110010101000101010001010100010101000101 + 010001010110FFFFFF00FFFFFF00FFFFFF000000008000000000010101000101 + 0100010101000000000000000080000000000101010001010100010101000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000010101000101 + 0100010101000000000000000011000000000101010001010100010101000000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101018901010100010101000101 + 0100010101000101010001010189010101000101010001010100010101000101 + 010001010189FFFFFF00FFFFFF00FFFFFF000101011401010100010101000101 + 0100010101000101010001010113010101000101010001010100010101000101 + 010001010113FFFFFF00FFFFFF00FFFFFF000101017B01010115010101A40101 + 0115010101A401010115010101A401010115010101A401010115010101A40101 + 01150101017BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010181010101AC010101AC0101 + 01AC010101AC010101AC010101AC010101AC010101AC010101AC010101AC0101 + 01AC01010181FFFFFF00FFFFFF00FFFFFF000101010E01010100010101000101 + 010001010100010101000101010D010101000101010001010100010101000101 + 01000101010DFFFFFF00FFFFFF00FFFFFF000000006B00000000010101000101 + 010001010100000000000000006B000000000101010001010100010101000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000010101000101 + 010001010100000000000000000E000000000101010001010100010101000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000010101000101 + 0100010101000000000000000071000000000101010001010100010101000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000101010F01010100010101000101 + 010001010100010101000101010F010101000101010001010100010101000101 + 01000101010FFFFFFF00FFFFFF00FFFFFF00010101BC010101BC010101BC0101 + 01BC010101BC010101BC010101BC010101BC010101BC010101BC010101BC0101 + 01BC010101BCFFFFFF00FFFFFF00FFFFFF000101011001010100010101000101 + 0100010101000101010001010110010101000101010001010100010101000101 + 010001010110FFFFFF00FFFFFF00FFFFFF000000008000000000010101000101 + 0100010101000000000000000080000000000101010001010100010101000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000010101000101 + 0100010101000000000000000011000000000000000001010100010101000000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101018901010100000000000000 + 0000000000000101010001010189010101000000000000000000000000000101 + 010001010189FFFFFF00FFFFFF00FFFFFF000101011400000000000000000000 + 0000000000000000000001010113010101000000000000000000000000000000 + 000001010113FFFFFF00FFFFFF00FFFFFF00000000AC000000E6000000E60000 + 00E6000000E6000000E6000000E6000000E6000000E6000000E6000000E60000 + 00E6000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101810000000D000000670000 + 000D000000670000000D000000670000000D000000670000000D000000670000 + 000D0000004DFFFFFF00FFFFFF00FFFFFF00010101AE01010100000000000000 + 000000000000000000000000000D000000000000000000000000000000000000 + 00000000000DFFFFFF00FFFFFF00FFFFFF00010101B001010100010101000000 + 000000000000000000000000006B000000000000000000000000000000000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF00010101B301010100010101000101 + 010000000000000000000000000E000000000000000000000000000000000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF00010101B601010100010101000000 + 0000000000000000000000000071000000000000000000000000000000000000 + 000000000071FFFFFF00FFFFFF00FFFFFF00010101B901010100000000000000 + 000000000000000000000000000F000000000000000000000000000000000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF00010101BC0000000F000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780000 + 000F00000078FFFFFF00FFFFFF00FFFFFF00010101C001010100000000000000 + 0000000000000000000000000010000000000000000000000000000000000000 + 000000000010FFFFFF00FFFFFF00FFFFFF00010101C401010100010101000000 + 0000000000000000000000000080000000000000000000000000000000000000 + 000000000080FFFFFF00FFFFFF00FFFFFF00010101C701010100010101000101 + 0100010101000000000000000011000000000101010001010100010101000000 + 000000000011FFFFFF00FFFFFF00FFFFFF00010101CC01010100010101000101 + 0100010101000101010001010189010101000101010001010100010101000101 + 010001010189FFFFFF00FFFFFF00FFFFFF00000000D901010100010101000101 + 0100010101000101010001010113010101000101010001010100010101000101 + 010001010113FFFFFF00FFFFFF00FFFFFF00000000AC01010115010101A40101 + 0115010101A401010115010101A401010115010101A401010115010101A40101 + 01150101017BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000004D0000000D000000670000 + 000D000000670000000D000000670000000D000000670000000D000000670101 + 010D01010181FFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000D000000000000000000000000000000000101 + 0100010101AEFFFFFF00FFFFFF00FFFFFF000000006B00000000000000000000 + 000000000000000000000000006B000000000000000000000000010101000101 + 0100010101B0FFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000E000000000000000001010100010101000101 + 0100010101B3FFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 0000000000000000000000000071000000000000000000000000010101000101 + 0100010101B6FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000000 + 000000000000000000000000000F000000000000000000000000000000000101 + 0100010101B9FFFFFF00FFFFFF00FFFFFF00000000780000000F000000780000 + 000F000000780000000F000000780000000F000000780000000F000000780101 + 010F010101BCFFFFFF00FFFFFF00FFFFFF000000001000000000000000000000 + 0000000000000000000000000010000000000000000000000000000000000101 + 0100010101C0FFFFFF00FFFFFF00FFFFFF000000008000000000000000000000 + 0000000000000000000000000080000000000000000000000000010101000101 + 0100010101C4FFFFFF00FFFFFF00FFFFFF000000001100000000010101000101 + 0100010101000000000000000011000000000101010001010100010101000101 + 0100010101C7FFFFFF00FFFFFF00FFFFFF000101018901010100010101000101 + 0100010101000101010001010189010101000101010001010100010101000101 + 0100010101CCFFFFFF00FFFFFF00FFFFFF000101011401010100010101000101 + 0100010101000101010001010113010101000101010001010100010101000101 + 0100000000D9FFFFFF00FFFFFF00FFFFFF000101017B01010115010101A40101 + 0115010101A401010115010101A401010115010101A401010115010101A40101 + 0115000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000004D0000000D000000670000 + 000D000000670101010D010101AC0000000D000000670000000D000000670000 + 000D0000004DFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 00000000000001010100010101AE010101000000000000000000000000000000 + 00000000000DFFFFFF00FFFFFF00FFFFFF000000006B00000000000000000000 + 00000101010001010100010101B0010101000101010000000000000000000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000101 + 01000101010001010100010101B3010101000101010001010100000000000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 00000101010001010100010101B6010101000101010000000000000000000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000000 + 00000000000001010100010101B9010101000000000000000000000000000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF00000000780000000F000000780000 + 000F000000780101010F010101BC0000000F000000780000000F000000780000 + 000F00000078FFFFFF00FFFFFF00FFFFFF000000001000000000000000000000 + 00000000000001010100010101C0010101000000000000000000000000000000 + 000000000010FFFFFF00FFFFFF00FFFFFF000000008000000000000000000000 + 00000101010001010100010101C4010101000101010000000000000000000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000010101000101 + 01000101010001010100010101C7010101000101010001010100010101000000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101018901010100010101000101 + 01000101010001010100010101CC010101000101010001010100010101000101 + 010001010189FFFFFF00FFFFFF00FFFFFF000101011401010100010101000101 + 01000101010001010100000000D9010101000101010001010100010101000101 + 010001010113FFFFFF00FFFFFF00FFFFFF000101017B01010115010101A40101 + 0115010101A401010115000000E601010115010101A401010115010101A40101 + 01150101017BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101810000000D000000670000 + 000D000000670101010D010101AC0000000D000000670000000D000000670101 + 010D01010181FFFFFF00FFFFFF00FFFFFF00010101AE01010100000000000000 + 00000000000001010100010101AE010101000000000000000000000000000101 + 0100010101AEFFFFFF00FFFFFF00FFFFFF00010101B001010100010101000000 + 00000101010001010100010101B0010101000101010000000000010101000101 + 0100010101B0FFFFFF00FFFFFF00FFFFFF00010101B301010100010101000101 + 01000101010001010100010101B3010101000101010001010100010101000101 + 0100010101B3FFFFFF00FFFFFF00FFFFFF00010101B601010100010101000000 + 00000101010001010100010101B6010101000101010000000000010101000101 + 0100010101B6FFFFFF00FFFFFF00FFFFFF00010101B901010100000000000000 + 00000000000001010100010101B9010101000000000000000000000000000101 + 0100010101B9FFFFFF00FFFFFF00FFFFFF00010101BC0000000F000000780000 + 000F000000780101010F010101BC0000000F000000780000000F000000780101 + 010F010101BCFFFFFF00FFFFFF00FFFFFF00010101C001010100000000000000 + 00000000000001010100010101C0010101000000000000000000000000000101 + 0100010101C0FFFFFF00FFFFFF00FFFFFF00010101C401010100010101000000 + 00000101010001010100010101C4010101000101010000000000010101000101 + 0100010101C4FFFFFF00FFFFFF00FFFFFF00010101C701010100010101000101 + 01000101010001010100010101C7010101000101010001010100010101000101 + 0100010101C7FFFFFF00FFFFFF00FFFFFF00010101CC01010100010101000101 + 01000101010001010100010101CC010101000101010001010100010101000101 + 0100010101CCFFFFFF00FFFFFF00FFFFFF00000000D901010100010101000101 + 01000101010001010100000000D9010101000101010001010100010101000101 + 0100000000D9FFFFFF00FFFFFF00FFFFFF00000000AC01010115010101A40101 + 0115010101A401010115000000E601010115010101A401010115010101A40101 + 0115000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000088CC610088CC810088 + CC810088CC810088CC810088CC810088CC810088CC810088CC810088CC810088 + CC810088CC610087CB00FFFFFF00FFFFFF00FFFFFF000087CA8388DCF4FF60C0 + E9FF5FBFEAFF80D3F4FF9CE3FDFFA2E6FFFFA2E6FFFFA2E6FFFFA2E6FFFFA6EA + FFFF0087CA830087CA00FFFFFF00FFFFFF00FFFFFF000085C885ACF1FFFFABEF + FEFF95E2F8FF6EC9EDFF48A8D9FF98DCFEFF98DCFEFF98DCFEFF98DCFEFFA1E5 + FFFF0085C8850085C800FFFFFF00FFFFFF00FFFFFF000084C587A9EEFDFFA4E9 + FCFFA4E9FCFFAAEEFDFF42A1D1FF97DBFDFF97DBFDFF97DBFDFF97DBFDFF9FE3 + FEFF0084C5870084C500FFFFFF00FFFFFF00FFFFFF000082C28AA6EBFCFFA1E6 + FBFFA1E6FBFFA6EBFCFF3C9DCFFF96DAFCFF96DAFCFF96DAFCFF96DAFCFF9EE2 + FDFF0082C28A0082C200FFFFFF00FFFFFF00FFFFFF00007FBF8DA3E8FBFF9DE3 + F9FF9DE3F9FFA3E8FBFF3594C5FF94D8FAFF94D8FAFF94D8FAFF94D8FAFF9BDF + FCFF007FBF8D007FBE00FFFFFF00FFFFFF00FFFFFF00007DBB909EE5F9FF98DF + F6FF98DFF6FF9EE5F9FF3290C0FF92D6F8FF92D6F8FF92D6F8FF92D6F8FF99DD + FAFF007DBB90007DBB33FFFFFF00FFFFFF00FFFFFF00007BB8949BE1F7FF94DB + F4FF94DBF4FF9BE1F7FF308DBCFF90D4F6FF90D4F6FF90D4F6FF90D4F6FF97DB + F9FFFEFEFDFF007BB894FFFFFF00FFFFFF00FFFFFF000078B49797DEF6FF90D8 + F2FF90D8F2FF97DEF6FF2D89B7FF8FD3F5FF8FD3F5FF8FD3F5FF8FD3F5FF95D9 + F8FFF5F5EEFF0078B497FFFFFF00FFFFFF00FFFFFF000076B09B92DAF4FF8BD4 + F0FF8BD4F0FF92DAF4FF2B85B3FF8DD1F3FF8DD1F3FF8DD1F3FF8DD1F3FF93D7 + F6FFEBEBDDFF0076B09BFFFFFF00FFFFFF00FFFFFF000073AC9E8ED6F2FF87D0 + EDFF87D0EDFF8ED6F2FF2882AFFF8BCFF1FF8BCFF1FF8BCFF1FF8BCFF1FF91D5 + F5FFFEC941FF0073AC9EFFFFFF00FFFFFF00FFFFFF00006FA7A48AD3F0FF82CD + EBFF82CDEBFF8AD3F0FF267EABFF8ACEF0FF8ACEF0FF8ACEF0FF8ACEF0FF8FD3 + F4FFF4B62EFF006FA7A4FFFFFF00FFFFFF00FFFFFF00006699B287D1EFFF7FCA + E9FF7FCAE9FF87D0EFFF267DA9FF8DD1F3FF8DD1F3FF8DD1F3FF8DD1F3FF90D4 + F5FF006699B200679B3EFFFFFF00FFFFFF00FFFFFF00005E8D8E3591BDF169B8 + DDFA81CBECFF84CEEEFF005C8BEF005D8CBE005D8CBE005D8CBE005D8CBE005D + 8CBE005E8D8E00669900FFFFFF00FFFFFF00FFFFFF00005D8C00006599500064 + 97991C7AA9C052A5CDE0005B89C1005B8900005B8900005B8900005B8900005B + 8900005D8C0000669900FFFFFF00FFFFFF00FFFFFF00005D8C00006497000062 + 9300005E8E30005C8C7C0059879200598700005B8900005B8900005B8900005B + 8900005D8C0000669900FFFFFF00BC6B3671BC6B3690BC6B36CCBC6B36EEBC6B + 36FABB6B36FEBB6B36FFBB6A36FFBB6A36FFBC6C39FFBD6E3BFFBB6D3AFFBB6B + 38EFBB703ECBB6693554FFFFFF00BC6B369BF6E0D1FFF7E0D1FFFEFBF8FFFEFB + F7FFFDF9F6FFFCF5F0FFFAF0EAFFFBF2EDFFFDF9F6FFFDFAF7FFFBF1EBFFF8E9 + DFFEECD0BDFBC9895EECB5693563BC6B36D8F6DFD1FFE9AA80FFFEFAF6FFFDFA + F6FFC88C64FFFBF3EEFFFBF1EAFFFCF6F2FFFEFBF8FFFCF6F1FFF9ECE2FFF8E7 + DBFFEED0BAFFECD0BDFFBB703EF8BC6B36F0F6DFD0FFE8A87EFFFCF6F1FFFCF6 + F1FFC88C64FFFAF1E9FFFBF4EEFFFDFAF7FFFDF9F6FFFAF0E8FFF8E8DDFFF7E6 + DBFFE1A37AFFEFD5C3FFB76935FEBC6B36FAF5DDCCFFE7A87EFFFAF0E8FFFAF0 + E8FFC98D66FFFAF0E9FFFDF8F3FFFEFAF8FFFCF4EFFFF9E9DFFFF7E7DBFFF7E5 + D9FFE0A278FFE7C2A9FFB66835FFBB6B36FEF4DCC9FFE7A77DFFF9ECE1FFF9EC + E1FFF9EDE3FFFCF4EEFFFDFAF7FFFDF7F3FFFAEDE5FFF7E7DBFFF7E5D9FFF6E5 + D8FFDEA077FFE4BEA4FFB46734FFBB6B36FFF4D9C7FFE6A67DFFC88C64FFC98D + 65FFC98E67FFCB926CFFCB926DFFCA9069FFC88C65FFC88C64FFC88C64FFC88C + 64FFDA9C74FFE1BA9FFFB36634FFBB6A36FFF2D8C5FFE3A47BFFE3A37AFFE3A4 + 7AFFE2A47BFFE2A37BFFE1A37BFFE1A279FFDFA077FFDE9F76FFDD9E74FFDB9C + 72FFDC9D74FFDDB59AFFB16534FFBB6A36FFF2D5C2FFE3A37AFFE3A37AFFE2A3 + 7BFFE2A37BFFE2A47BFFE1A279FFE0A178FFDEA077FFDE9E75FFDC9D74FFDA9B + 73FFD99B73FFDAB095FFAF6433FFBB6A36FFF0D2BEFFE2A37AFFE2A37AFFE1A3 + 7AFFE2A37BFFE1A37BFFE0A178FFDE9F77FFDD9F76FFDC9D74FFD99B72FFD899 + 71FFD69970FFD5AB8EFFAD6333FFBA6A36FFEFD0BBFFE2A27AFFFEFBF8FFFEFB + F8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFB + F8FFD3966DFFD2A78AFFAB6232FFBB6B38FFEFCEB8FFE1A279FFFEFAF7FF62C0 + 88FF62C088FF62C088FF62C088FF62C088FF62C088FF62C088FF62C088FFFDF9 + F6FFCF936AFFCEA384FFAA6132FFBB6C38FFEECCB6FFE1A27AFFFEFAF7FFBFDC + C2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFFDF9 + F6FFCD9068FFCC9E81FFA86132FFBA6B37FEEDCAB3FFE0A27AFFFEFAF7FF62C0 + 88FF62C088FF62C088FF62C088FF62C088FF62C088FF62C088FF62C088FFFDF9 + F6FFCA8D65FFC99B7CFFA76031FEBA6A35DEEBC6ADFFEAC5ADFFFEFBF8FFFEFB + F8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFB + F8FFC89A7CFFC79879FFA76031EDBA6A3600B96935B5B86935EEB76835FFB568 + 35FFB46734FFB26634FFB06533FFAE6433FFAC6332FFAA6232FFA96132FFA860 + 31FFA76031FEA66031F1A86131C4FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00016395000163940001629300016192000162 + 930001629300016394000000000001334C00016597000164960001639400003A + 8C00003E9248003C8FCC00378A48016395000163940001629300016192000162 + 930001629300016394000000000001334C390165969C0164959C0163943E0039 + 8B48003688CC5285C9FF002E7ECC016395000163940001629300016192000162 + 93000162930001639400000000240000006788CCDDFF87CBDDFF016091AF0030 + 80CC3F72B6FF002774CC00247048016395000163940001629300016192000162 + 9300016293100162936D00000069DDDCDCFF949494FF70B4D6FF80C4DBFF015C + 8DB2001A63CC0013584800226E00016395050163941401629328016192410161 + 9277106C9AAB4B9BBADB79B9D5FC919191FFD9D4D4FF8D8D8DFF68ACCEFF74B8 + D4FF015887B4015686400155840001629383126D9BB82078A2C33385ABD058A2 + C0E774B9D1FB6EACCCFF669DC8FF83C7DAFF888888FFD3CACAFF838383FF60A4 + C6FF63A7C9FF015382A5015281000160913E015E8FB16AAEC9FF66A8C5FF5692 + B8FF4B80AFFF5D97BFFF77B9D2FF669DC8FF7BBAD5FF7E7E7EFFCEC0C0FF7979 + 79FF5588BBFF014F7EA6014E7D00015F9000002B5548002B55CC336898FF508C + B3FF69ABC8FF67A7C6FF4D80B3FF71B1CEFF6EA9CDFF6CA3CEFF6D6D6DFFAA99 + 99FF010101A5014C7A42014B7A00015F9000002B55000157873F015585B65FA1 + C0FF3F79A3FF4278A7FF66A6C5FF619DC2FF5E95C1FF74B4D1FF6598CBFF0101 + 01AB0101013C014B7900014B7A00015F9000002B550001568600002B5548002B + 55CC4F8DB3FF68ACC8FF4880ACFF5087B3FF6AAAC8FF5588BBFF00416EC1003E + 6A4401010100014B7900014B7A00015F9000002B550001568600002B5500014D + 7C41014B79BB3A719FFF386F9DFF5F9FC0FF4578ABFF003763C600356046003C + 680001010100014B7900014B7A00015F9000002B550001568600002B5500014C + 7B00002B5548002B55CC5494B7FF34679AFF00305ACA002D584800335E00003C + 680001010100014B7900014B7A00015F9000002B550001568600002B5500014C + 7B00002B550000315C47002D57CC002C56CC002B5548002C570000335E00003C + 680001010100014B7900014B7A00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00A2AE8EFF5F9771FF4F8E + 66FF49895FFFA2AE8EFFFFFFFF00FFFFFF00EFC2A37EEFC1A2E3EDC09FFFEBBE + 9DFFEBBC9AFFE9BA96FFE7B793FFE6B590FF9DAF91FF61AB81FF95D4B4FFBAE6 + D0FF6ABB8FFF2D8F57FF196B378CFFFFFF00EEC1A1EBFBF7F4FFFBF7F4FFFBF7 + F4FFFBF7F4FFFBF7F4FFFBF7F4FFFBF7F4FF498960FF90D3B1FF92D6B1FFFFFF + FFFF65BC8CFF67BC8FFF196B37F7FFFFFF00ECBF9EFFFBF7F4FF9CD5A5FF98D3 + A1FF94D09DFF90CE98FF8BCB93FF87C98EFF317B4CFF9CD4B6FFFFFFFFFFFFFF + FFFFFFFFFFFF95D2B2FF196B37FFFFFFFF00EBBD9BFFFBF7F4FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22703EFF62BA8BFF60BA87FFFFFF + FFFF60B987FF67BC8FFF196B37F7FFFFFF00E9BA98FFFBF7F4FF4FA358FF4FA3 + 58FF59B163FFE9C3A6FFE9C3A6FFE9C3A6FFA2AE8EFF288C53FF64BA8DFF95D2 + B2FF64BA8DFF288C53FF196B378CFFFFFF00E7B794FFFBF7F4FF489B51FFB9DF + BDFF54AB5EFFFFFFFFFFFFFFFFFFFFFFFFFFE8C7ACFF84B094FF257341FF196B + 37FF247240FF6C7C4AFFFFFFFF00FFFFFF00E5B48FFFFAF6F2FF42924AFFB6DD + BAFF4FA358FFE9C7ADFFE9C9AEFFE9C9B0FFE8C7ACFFE9C9B0FFE8C8B0FFE8CC + B5FFF2E7DEFFC88A59FFFFFFFF00FFFFFF00E3B18CFFFAF6F1FF3B8842FFACD8 + B0FF489B51FFFFFFFFFFFFFFFFFFFFFFFFFFE8C7ACFFFFFFFFFFFFFFFFFFFFFF + FFFFF1E5DBFFC68655FFFFFFFF00FFFFFF00E1AE87FFFAF4F0FF347E3AFFA0D3 + A4FF42924AFFEACCB3FFEACCB3FFEACEB7FFE8C7ACFFE8C7ACFFE8C8B0FFE8C8 + AEFFF0E2D8FFC48654FFFFFFFF00FFFFFF00DFAA82FFF9F3EFFF2E7533FF92CC + 97FF3B8842FFFFFFFFFFFFFFFFFFFFFFFFFFEACFBAFFFBF6F2FFFFFFFFFFFFFF + FFFFF0E2D8FFC88D5FFFFFFFFF00FFFFFF00DDA87EFFF9F3EFFF276D2CFF84C6 + 8AFF347E3AFFEBD0BBFFEBD0BBFFEBD1BDFFEACDB5FFEACDB5FFEACDB5FFEACD + B5FFF0E2D8FFC68A5CFFFFFFFF00FFFFFF00D9A47AFFF9F3EEFF1D5F21FF2265 + 26FF276D2CFFFFFFFFFFFFFFFFFFFFFFFFFFEAC7ADFFFFFFFFFFFFFFFFFFFFFF + FFFFF0E2D8FFC68C5FFFFFFFFF00FFFFFF00D7A175FFF8F2EDFFF7F0EAFFF6ED + E6FFF4EAE2FFF3E7DEFFF1E4DBFFF0E2D8FFF0E2D8FFF0E2D8FFF0E2D8FFF0E2 + D8FFF0E2D8FFC58A5DFDFFFFFF00FFFFFF00D69E72C4D3996EF4D19668FFCE92 + 63FFCB8E5EFFC98A5BFFC78756FFC38452FFC38452FFC38452FFC38452FFC384 + 52FFC38452FFBB7742B0FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00A2AE8EFF5F9771FF4F8E + 66FF49895FFFA2AE8EFFFFFFFF00FFFFFF00EFC2A37EEFC1A2E3EDC09FFFEBBE + 9DFFEBBC9AFFE9BA96FFE7B793FFE6B590FF9DAF91FF61AB81FF95D4B4FFBAE6 + D0FF6ABB8FFF2D8F57FF196B378CFFFFFF00EEC1A1EBFBF7F4FFFBF7F4FFFBF7 + F4FFFBF7F4FFFBF7F4FFFBF7F4FFFBF7F4FF498960FF90D3B1FF92D6B1FFFFFF + FFFF65BC8CFF67BC8FFF196B37F7FFFFFF00ECBF9EFFFBF7F4FF9CD5A5FF98D3 + A1FF94D09DFF90CE98FF8BCB93FF87C98EFF317B4CFF9CD4B6FFFFFFFFFFFFFF + FFFFFFFFFFFF95D2B2FF196B37FFFFFFFF00EBBD9BFFFBF7F4FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22703EFF62BA8BFF60BA87FFFFFF + FFFF60B987FF67BC8FFF196B37F7FFFFFF00E9BA98FFFBF7F4FFE9C3A6FFE9C3 + A6FFE9C3A6FFE9C3A6FFE9C3A6FFE9C3A6FFA2AE8EFF288C53FF64BA8DFF95D2 + B2FF64BA8DFF288C53FF196B378CFFFFFF00E7B794FFFBF7F4FFE9C3A6FFFFFF + FFFFE8C4A9FFFFFFFFFFFFFFFFFFFFFFFFFFE8C7ACFF84B094FF257341FF196B + 37FF247240FF6C7C4AFFFFFFFF00FFFFFF00E5B48FFFFAF6F2FFE9C6AAFFE9C6 + ACFFEAC7ACFFE9C7ADFFE9C9AEFFE9C9B0FFE8C7ACFFE9C9B0FFE8C8B0FFE8CC + B5FFF2E7DEFFC88A59FFFFFFFF00FFFFFF00E3B18CFFFAF6F1FFEAC9AEFFFFFF + FFFFEAC9B0FFFFFFFFFFFFFFFFFFFFFFFFFFE8C7ACFFFFFFFFFFFFFFFFFFFFFF + FFFFF1E5DBFFC68655FFFFFFFF00FFFFFF00E1AE87FFFAF4F0FF59B163FF54AB + 5EFF4FA358FF4FA358FF489B51FF42924AFF3B8842FF347E3AFF2E7533FF276D + 2CFFF0E2D8FFC48654FFFFFFFF00FFFFFF00DFAA82FFF9F3EFFF58B162FFB9DF + BDFFB6DDBAFFB6DDBAFFACD8B0FFA0D3A4FF92CC97FF84C68AFF79C17EFF2265 + 26FFF0E2D8FFC88D5FFFFFFFFF00FFFFFF00DDA87EFFF9F3EFFF4FA358FF489B + 51FF42924AFF42924AFF3B8842FF347E3AFF2E7533FF276D2CFF226526FF1D5F + 21FFF0E2D8FFC68A5CFFFFFFFF00FFFFFF00D9A47AFFF9F3EEFFEBD2BEFFFFFF + FFFFEBD3BFFFFFFFFFFFFFFFFFFFFFFFFFFFEAC7ADFFFFFFFFFFFFFFFFFFFFFF + FFFFF0E2D8FFC68C5FFFFFFFFF00FFFFFF00D7A175FFF8F2EDFFF7F0EAFFF6ED + E6FFF4EAE2FFF3E7DEFFF1E4DBFFF0E2D8FFF0E2D8FFF0E2D8FFF0E2D8FFF0E2 + D8FFF0E2D8FFC58A5DFDFFFFFF00FFFFFF00D69E72C4D3996EF4D19668FFCE92 + 63FFCB8E5EFFC98A5BFFC78756FFC38452FFC38452FFC38452FFC38452FFC384 + 52FFC38452FFBB7742B0FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF007591C3FF235BC0FF0543 + BCFF1D58BFFF7591C2FFFFFFFF00FFFFFF00EFC2A37EEFC1A2E3EDC09FFFEBBE + 9DFFEBBC9AFFE9BA96FFE7B793FFE6B590FF96B1E3FF3D76D2FF8DB5F7FFB8D6 + FEFF72A8F5FF2E6BCAFF0443BA6DFFFFFF00EEC1A1EBFBF7F4FFFBF7F4FFFBF7 + F4FFFBF7F4FFFBF7F4FFFBF7F4FFFBF7F4FF255DC2FF8DB5F6FF4D92FFFF1177 + FFFF2186FFFF408AEBFF0344B9DEFFFFFF00ECBF9EFFFBF7F4FF9CD5A5FF98D3 + A1FF94D09DFF90CE98FF8BCB93FF87C98EFF0543BCFFAECDFEFFFFFFFFFFFFFF + FFFFFFFFFFFF187FEFFF0442BCFEFFFFFF00EBBD9BFFFBF7F4FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF164BAEFF639DF4FF187FFFFF0076 + F8FF0076EEFF0368E1FF0345B9E4FFFFFF00E9BA98FFFBF7F4FF6D6FFCFF7478 + FEFF7478FEFFE9C3A6FFE9C3A6FFE9C3A6FF818DB5FF2865C8FF2177E6FF0579 + EAFF0164DDFF064EBCFF0345B87AFFFFFF00E7B794FFFBF7F4FF6263FAFFC4CE + FDFF7478FEFFFFFFFFFFFFFFFFFFFFFFFFFFE8C7ACFF95B0E3FF235CC2FF0543 + BCFF1E58BEFF6B6C8AFFFFFFFF00FFFFFF00E5B48FFFFAF6F2FF5654F7FFC1CB + FCFF6D6FFCFFE9C7ADFFE9C9AEFFE9C9B0FFE8C7ACFFE9C9B0FFE8C8B0FFE8CC + B5FFF2E7DEFFC88A59FFFFFFFF00FFFFFF00E3B18CFFFAF6F1FF3A35F1FFB1B9 + FBFF5654F7FFFFFFFFFFFFFFFFFFFFFFFFFFE8C7ACFFFFFFFFFFFFFFFFFFFFFF + FFFFF1E5DBFFC68655FFFFFFFF00FFFFFF00E1AE87FFFAF4F0FF2E26EEFFA6AD + FBFF4845F4FFEACCB3FFEACCB3FFEACEB7FFE8C7ACFFE8C7ACFFE8C8B0FFE8C8 + AEFFF0E2D8FFC48654FFFFFFFF00FFFFFF00DFAA82FFF9F3EFFF231AECFF9CA2 + FAFF3A35F1FFFFFFFFFFFFFFFFFFFFFFFFFFEACFBAFFFBF6F2FFFFFFFFFFFFFF + FFFFF0E2D8FFC88D5FFFFFFFFF00FFFFFF00DDA87EFFF9F3EFFF1C11EAFF9399 + F9FF2E26EEFFEBD0BBFFEBD0BBFFEBD1BDFFEACDB5FFEACDB5FFEACDB5FFEACD + B5FFF0E2D8FFC68A5CFFFFFFFF00FFFFFF00D9A47AFFF9F3EEFF1C11EAFF1C11 + EAFF231AECFFFFFFFFFFFFFFFFFFFFFFFFFFEAC7ADFFFFFFFFFFFFFFFFFFFFFF + FFFFF0E2D8FFC68C5FFFFFFFFF00FFFFFF00D7A175FFF8F2EDFFF7F0EAFFF6ED + E6FFF4EAE2FFF3E7DEFFF1E4DBFFF0E2D8FFF0E2D8FFF0E2D8FFF0E2D8FFF0E2 + D8FFF0E2D8FFC58A5DFDFFFFFF00FFFFFF00D69E72C4D3996EF4D19668FFCE92 + 63FFCB8E5EFFC98A5BFFC78756FFC38452FFC38452FFC38452FFC38452FFC384 + 52FFC38452FFBB7742B0FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF007590C3FF2359BFFF0541 + BBFF1D55BFFF758FC1FFFFFFFF00FFFFFF00EFC1A37EEFC0A1E3EDBF9FFFEBBD + 9DFFEBBB99FFE9B995FFE7B693FFE6B390FF95B0E3FF3D73D1FF8DB3F7FFB8D5 + FEFF71A5F5FF2E69CAFF0440BA6DFFFFFF00EEBFA0EBFBF6F3FFFBF6F3FFFBF6 + F3FFFBF6F3FFFBF6F3FFFBF6F3FFFBF6F3FF255BC1FF8CB2F6FF4D91FFFF1174 + FFFF2184FFFF3F86EBFF0342B9DEFFFFFF00ECBE9EFFFBF6F3FF9BD5A3FF97D3 + A0FF94D09DFF90CE97FF8BCB92FF87C98DFF0541BBFFAECCFEFFFFFFFFFFFFFF + FFFFFFFFFFFF187BEEFF0441BCFEFFFFFF00EBBC9BFFFBF6F3FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1648AEFF629CF4FF177BFFFF0073 + F8FF0073EEFF0366E1FF0342B9E4FFFFFF00E9B997FFFBF6F3FFE9C1A5FFE9C1 + A5FFE9C1A5FFE9C1A5FFE9C1A5FFE9C1A5FF818CB5FF2862C8FF2075E6FF0577 + E9FF0164DDFF064BBCFF0342B77AFFFFFF00E7B693FFFBF6F3FFE9C1A5FFFFFF + FFFFE8C2A8FFFFFFFFFFFFFFFFFFFFFFFFFFE8C7ACFF95AFE3FF235AC1FF0541 + BBFF1E56BEFF6B6B89FFFFFFFF00FFFFFF00E5B28FFFFAF6F2FFE9C4A9FFE9C4 + ABFFEAC6ACFFE9C7ADFFE9C8ADFFE9C8AFFFE8C7ACFFE9C8AFFFE8C7B0FFE8CB + B4FFF2E7DEFFC88858FFFFFFFF00FFFFFF00E3AF8BFFFAF5F0FFEAC9AEFFFFFF + FFFFEAC8B0FFFFFFFFFFFFFFFFFFFFFFFFFFE8C7ACFFFFFFFFFFFFFFFFFFFFFF + FFFFF1E4DBFFC58555FFFFFFFF00FFFFFF00E1AE87FFFAF4F0FF7476FEFF7476 + FEFF7476FEFF6C6CFCFF6262FAFF5353F7FF4644F4FF3835F1FF2C26EEFF211A + ECFFF0E2D8FFC48454FFFFFFFF00FFFFFF00DFA881FFF9F3EFFF7476FEFFC3CC + FDFFC3CCFDFFC0CAFCFFBAC2FCFFB1B8FBFFA5AAFBFF9CA0FAFF9398F9FF1B11 + E9FFF0E2D8FFC88B5EFFFFFFFF00FFFFFF00DDA67DFFF9F3EFFF6C6CFCFF6262 + FAFF6262FAFF5353F7FF4644F4FF3835F1FF2C26EEFF211AECFF1B11E9FF1B11 + E9FFF0E2D8FFC6895CFFFFFFFF00FFFFFF00D9A279FFF9F2EDFFEBD0BDFFFFFF + FFFFEBD2BFFFFFFFFFFFFFFFFFFFFFFFFFFFEAC5ACFFFFFFFFFFFFFFFFFFFFFF + FFFFF0E2D8FFC68B5EFFFFFFFF00FFFFFF00D79F75FFF8F1ECFFF7EFE9FFF6EC + E6FFF4E9E2FFF3E6DDFFF1E3DBFFF0E2D8FFF0E2D8FFF0E2D8FFF0E2D8FFF0E2 + D8FFF0E2D8FFC5885DFDFFFFFF00FFFFFF00D69D72C4D3976DF4D09568FFCE90 + 62FFCB8C5DFFC9885BFFC78655FFC28252FFC28252FFC28252FFC28252FFC282 + 52FFC28252FFBA7642B0FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00C77947AACC8655CECC8857DECB8856DBCC88 + 56DBCB8757DBCA8350D0C479426EB2673C08FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00CA8554D0FFFFFFDBFDF3E9DEFDF3EADEFCF2 + E8DEFAEFE3DEFAF2E7DEEABB88DECF85559CB4693D0AFFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00CB8656DAFEF5EDDEFCDEC5DEFBE0C7DEF9DC + C2DEF5D3B4DEFEF9F3DEFAE2C4DEECC193DEC37D4880FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00CB8655DBFEF6F0DEFCE2CDDEFCE3CDDEFADF + C8DEF7D9BCDEF5E9DDDEFAF3EBDEFBF8F3DECD9565DCFFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00CB8655DBFEF7F1DEFCE5D2DEFCE4D1DEFBE2 + CCDEF9DDC4DEEAC39DFFE6BF96FFE4BB92FFE4BB92FFD1A06CF5D09E6DF6CC96 + 5FDAC479427EB2673C09FFFFFF00CB8654DBFFF7F2DEFEE7D5DEFEE7D5DEFDE5 + D1DEFAE0CADEE5BE96FFFFFFFEFFFDF3E9FFFDF3EAFFFCF2E8FFFAEFE3FFFAF2 + E7FFEABB88FFCF8555B3B4693D0CCB8553DBFFF7F0DEFFE7D5DEFDE7D6DEFDE6 + D4DEFCE4D0DEE4BB93FFFEF5EDFFFCDEC5FFFBE0C7FFF9DCC2FFF5D3B4FFFEF9 + F3FFFAE2C4FFECC193FFC37D4893CA8452DBFFF7F1DEFFE9D9DEFFEADBDEFFE9 + D9DEFFE7D7DEE4BB92FFFEF6F0FFFCE2CDFFFCE3CDFFFADFC8FFF7D9BCFFF5E9 + DDFFFAF3EBFFFBF8F3FFCA8353FECC8352DBFBF5EEDEFFE9D9DEFFEADBDEFFE9 + D9DEFFE7D7DEE4BB92FFFEF7F1FFFCE5D2FFFCE4D1FFFBE2CCFFF9DDC4FFF6D7 + BBFFF3D1AFFFFAEFE4FFCC8758FECF8253DEEFF1E7DEFFE9D9DEFFEADBDEFFE9 + D9DEFFE7D7DEE4BB91FFFFF7F2FFFEE7D5FFFEE7D5FFFDE5D1FFFAE0CAFFF9DE + C4FFF7D9BCFFFDF2E7FFCC8757FEC87C4ED3FCF3ECDEFAF1E8DEFAF0E7DEFBF1 + E9DEFBF2EADEE4BA91FFFFF7F0FFFFE7D5FFFDE7D6FFFDE6D4FFFCE4D0FFFBE3 + CBFFFADCC2FFFEF3E8FFCC8656FEC7794AB9C8794BCEC87545DDC77545D4C875 + 45D4C77545D4CA8452FFFFF7F1FFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5 + D2FFFFE2CBFFFFF7F1FFCB8555FEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00CC8352FBFBF5EEFFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5 + D2FFFFE2CBFFFBF6EFFFCC8355FEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00CF8253FFEFF1E7FFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5 + D2FFFFE2CBFFEFF2E8FFCE8156FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00C77949EDFCF3ECFFFAF1E8FFFAF0E7FFFBF1E9FFFBF2EAFFFBF2 + EAFFFBF2EBFFFDF4EEFFCA8054F9FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00C57342C1C67545E6C87545FEC77545F3C87545F3C77545F3C775 + 45F3C87546F4C57444E8CA7F53F1FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00996A252AA77B3E9E92611905FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00A67B3E69CBAE87E4905D1409FFFFFF00FFFFFF00FFFF + FF0092601702FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00A97E436ED5BC9DF89261190FFFFFFF00FFFFFF009867 + 222DAE854CB5FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00AB814774DEC8AEFF95641D1EFFFFFF0093601827D1B6 + 93E4BB9767B6FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00AD844C7BE6D4C0FF96651E248F5C121DD3B999DCD3B8 + 97E1915E1518FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00AF875084EDDECEFF97662063CEB38FCBE7D6C3FC9666 + 203BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00B28A5489F1E2D3FFCFB38EF6F5E9DCFFA276376CFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF005E3D0D02FFFFFF00B68F598BF5E9DDFFE2CDB4FFB99461A0FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006644121A9D69 + 32ABB17E42D29E682CA4BC9767CDF0E0D0FFB6915FC581531104FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0066431218B17E42DBDCAA + 60FFD09E54F3EAB365FFD8BA99FFF8EBE1FFAE8957BC57390D41FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF009C6A32ACD6A55EFD704D + 1A3E6E4B184FE4AD60FFDCBD9BFFEFCDA5FFEFB767FFD8A65DFF66491D64FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00BE8A4AF2A87E41B6FFFF + FF00966E3297E7B066FFCAA274FEE5B167FF945E2DC1B88D4DD3AF703BF44930 + 0B08FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B58244E7D6A45AE8AE82 + 41C5ECB666FFA76E36D8AC6C37EBC49551F3FFFFFF0076562776B77840FF5238 + 121BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0077531E56C79751ECD8A6 + 5AFEA66C36CB51350A18A86835E1D1A057FA412A091E8E6A369CB4753FFC4D33 + 0D10FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00674514186A48 + 1620FFFFFF00FFFFFF009F5E2FC6E7B263FFBF924FE5DDAB62FFA26232D8FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF004A310C07A06131D7B6763FF7A46534E04B320C14FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF002063982A206398FF2063 + 98FF206398FF206398FF206398FF206398F0FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0020639832206398B2206398FF3775A4FFB6EF + FEFF80DBF3FF80DBF3FFB6EFFEFF2E6EA1FF206398FF206398A520639853FFFF + FF00FFFFFF00FFFFFF00FFFFFF00206398E094C9E0FDAEE2F2FF4E9DDFFFB5EE + FDFF75D4F0FF75D4F0FFB5EEFDFF4B9BDEFF8ECBE9FF8DCAE8F2206398F3FFFF + FF00FFFFFF00FFFFFF00FFFFFF00206398FFB0E1F2FF79BDE2FF4498DDFF4497 + DCFF4396DCFF4296DCFF4295DCFF4195DBFF539ED4FF89C6E6FF206398FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00206398FFAADDF1FF74B9E0FF70B6DFFF6CB3 + DDFF6BB2DCFFD9AF84FFD7AE81FFD7AC7FFFD7AC7FFFCCA070FFCD9F71FFB38F + 67FFCB8856D6B2673C09FFFFFF00206398FFA5DAEFFF6FB5DEFF68B0DCFF60A9 + D9FF5FA9D9FFD7AD81FFFFFFFEFFFDF3E9FFFDF3EAFFFCF2E8FFFAEFE3FFFAF2 + E7FFEABB88FFCE8959E7B4693D0C206398FF9ED6EDFF6BB2DCFF66AFDCFF60AA + DAFF5FA9D9FFD9AF84FFFEF5EDFFFCDEC5FFFBE0C7FFF9DCC2FFF5D3B4FFFEF9 + F3FFFAE2C4FFECC193FFCB8857DC206398FF98D2EBFF65AEDAFF60AAD9FF5DA6 + D8FF5CA5D7FFD9AF84FFFEF6F0FFFCE2CDFFFCE3CDFFFADFC8FFF7D9BCFFF5E9 + DDFFFAF3EBFFFBF8F3FFCA8353FE206398FF91CDE9FF5FA9D9FF5DA5D8FF5AA0 + D6FF599FD6FFD8AD81FFFEF7F1FFFCE5D2FFFCE4D1FFFBE2CCFFF9DDC4FFF6D7 + BBFFF3D1AFFFFAEFE4FFCC8758FE206398FF8BC9E7FF5CA5D7FF59A0D5FF579C + D3FF569AD3FFD7AC7FFFFFF7F2FFFEE7D5FFFEE7D5FFFDE5D1FFFAE0CAFFF9DE + C4FFF7D9BCFFFDF2E7FFCC8757FE206398FF88C4E6FF599FD6FF569BD3FF5397 + D1FF5395D1FFD7AC7FFFFFF7F0FFFFE7D5FFFDE7D6FFFDE6D4FFFCE4D0FFFBE3 + CBFFFADCC2FFFEF3E8FFCC8656FE206398FF84BFE2FF569AD3FF5397D1FF5092 + CFFF5091CFFFD6A97DFFFFF7F1FFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5 + D2FFFFE2CBFFFFF7F1FFCB8555FE206398FF80B9E1FF5395D1FF5092D0FF4E8E + CEFF4D8CCDFFD6A97DFFFBF5EEFFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5 + D2FFFFE2CBFFFBF6EFFFCC8355FE206398C274ADD8FF7BB2DDFF78AEDCFF75AA + DAFF74A9DAFFDAA97DFFEFF1E7FFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5 + D2FFFFE2CBFFEFF2E8FFCE8156FF2063984A206398CF206398FF206398FF2063 + 98FF206398FFC98F67FFFCF3ECFFFAF1E8FFFAF0E7FFFBF1E9FFFBF2EAFFFBF2 + EAFFFBF2EBFFFDF4EEFFCA8054F9FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00C57342C1C67545E6C87545FEC77545F3C87545F3C77545F3C775 + 45F3C87546F4C57444E8CA7F53F1000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000026EB628026EB669026EB679026E + B679026EB679026EB679026EB679026EB679026EB679026EB679026EB679026E + B679026EB669026EB6280000000000000000026DB46BC1E3F1D9E6FBFFFFE5FA + FFFFE5FAFFFFE5FAFFFFE5FAFFFFE5FAFFFFE5FAFFFFE4FAFFFFE4FAFFFFE5FA + FFFFBDE2F1D9026DB46B0000000000000000026BB17EE5FAFFFFD9F4FFFFD9F4 + FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4 + FFFFE0F8FFFF026BB17E0000000000000000026AAE81E0F9FFFFD4F2FFFFD4F2 + FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2 + FFFFD9F5FFFF026AAE8100000000000000000268AB84DCF7FFFFCFF0FFFFCFF0 + FFFFCFF0FFFFC2EDFCFFA8E8F4FF91E3EDFF84E0E9FF7CDEE7FF7CDEE7FF84E0 + E9FF9CE6EFFF0268AB8400000000000000000266A788D8F4FFFFCCEEFFFFC2EC + FCFF9DE5F1FF85E0EAFF82E0E9FF82E0E9FF82E0E9FF82E0E9FF82E0E9FF82E0 + E9FF8AE2EBFF0266A78800000000000000000264A48CD6F3FFFFB6EBF9FF94E4 + F0FF8FE3EEFF8FE3EEFF8FE3EEFF8FE3EEFF8FE3EEFF45C05FFF2DB42FFF45C0 + 5FFF91E4EFFF0264A48C00000000000000000261A090C1EFFBFF9EE7F4FF9DE6 + F4FF9DE6F4FF9DE6F4FF9DE6F4FF9DE6F4FF9DE6F4FF2FB130FF75EE64FF2FB1 + 30FF9DE6F4FF0261A0900000000000000000025F9C8191D0E6E1B0ECF9FFAEEB + F9FFADEBF9FFACEBF9FFABEAF9FF4EBB63FF30AC31FF30AC31FF66EB55FF30AC + 31FF26A529F90D8C27CD0000000000000000025C9832025C9785025C9799025C + 9799B7EDFDFF025C9799025C97990E8D13EB52E741FF52E741FF52E741FF52E7 + 41FF52E741FF0F9207D600000000000000000000000000000000000000000355 + 8BA603558BA603568D39035993020E8D00990E8C00CC0E8C00CC3DE22CFF0E8C + 00CC0E8C00CC0E8D00990000000000000000000000000000000000000000034D + 7DB5034E7F3D000000000000000000000000000000000C8300CC2BDF1AFF0C83 + 00CC000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000066D0099056900CC066D + 0099000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000026EB628026EB669026EB679026E + B679026EB679026EB679026EB679026EB679026EB679026EB679026EB679026E + B679026EB669026EB6280000000000000000026DB46BC1E3F1D9E6FBFFFFE5FA + FFFFE5FAFFFFE5FAFFFFE5FAFFFFE5FAFFFFE5FAFFFFE4FAFFFFE4FAFFFFE5FA + FFFFBDE2F1D9026DB46B0000000000000000026BB17EE5FAFFFFD9F4FFFFD9F4 + FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4 + FFFFE0F8FFFF026BB17E0000000000000000026AAE81E0F9FFFFD4F2FFFFD4F2 + FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2 + FFFFD9F5FFFF026AAE8100000000000000000268AB84DCF7FFFFCFF0FFFFCFF0 + FFFFCFF0FFFFC2EDFCFFA8E8F4FF91E3EDFF84E0E9FF7CDEE7FF7CDEE7FF84E0 + E9FF9CE6EFFF0268AB8400000000000000000266A788D8F4FFFFCCEEFFFFC2EC + FCFF9DE5F1FF85E0EAFF82E0E9FF82E0E9FF82E0E9FF82E0E9FF82E0E9FF82E0 + E9FF8AE2EBFF0266A78800000000000000000264A48CD6F3FFFFB6EBF9FF94E4 + F0FF8FE3EEFF8FE3EEFF8FE3EEFF8FE3EEFF8FE3EEFF8FE3EEFF8FE3EEFF8FE3 + EEFF91E4EFFF0264A48C00000000000000000261A090C1EFFBFF9EE7F4FF9DE6 + F4FF9DE6F4FF9DE6F4FF9DE6F4FF9DE6F4FF9DE6F4FF9DE6F4FF9DE6F4FF9DE6 + F4FF9DE6F4FF0261A0900000000000000000025F9C8191D0E6E1B0ECF9FFAEEB + F9FFADEBF9FFACEBF9FFABEAF9FF445DC7FF222EB7FF222EB7FF222EB7FF222E + B7FF1824B2F90018A3CD0000000000000000025C9832025C9785025C9799025C + 9799B7EDFDFF025C9799025C9799000C97EB5E5EF7FF5E5EF7FF5E5EF7FF5E5E + F7FF5E5EF7FF000498D600000000000000000000000000000000000000000355 + 8BA603558BA603568D390359930200008499000080CC000080CC000080CC0000 + 80CC000080CC000084990000000000000000000000000000000000000000034D + 7DB5034E7F3D0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000026EB628026EB669026EB679026E + B679026EB679026EB679026EB679026EB679026EB679026EB679026EB679026E + B679026EB669026EB6280000000000000000026DB46BC1E3F1D9E6FBFFFFE5FA + FFFFE5FAFFFFE5FAFFFFE5FAFFFFE5FAFFFFE5FAFFFFE4FAFFFFE4FAFFFFE5FA + FFFFBDE2F1D9026DB46B0000000000000000026BB17EE5FAFFFFD9F4FFFFD9F4 + FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4FFFFD9F4 + FFFFE0F8FFFF026BB17E0000000000000000026AAE81E0F9FFFFD4F2FFFFD4F2 + FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2FFFFD4F2 + FFFFD9F5FFFF026AAE8100000000000000000268AB84DCF7FFFFCFF0FFFFCFF0 + FFFFCFF0FFFFC2EDFCFFA8E8F4FF91E3EDFF84E0E9FF7CDEE7FF7CDEE7FF70B7 + D8FF3148E3FF013FB5A300000000000000000266A788D8F4FFFFCCEEFFFFC2EC + FCFF9DE5F1FF85E0EAFF82E0E9FF82E0E9FF82E0E9FF82E0E9FF7BCCD3FF5E8E + ADFF8080FFFF010FAFE200000000000000000264A48CD6F3FFFFB6EBF9FF94E4 + F0FF8FE3EEFF8FE3EEFF8FE3EEFF8FE3EEFF8FE3EEFF6BD2E1FF71A2A8FFF7F7 + F7FF4E7390FF013BA1AC00000000000000000261A090C1EFFBFF9EE7F4FF9DE6 + F4FF9DE6F4FF9DE6F4FF9DE6F4FF9DE6F4FF76D5E5FF2EADC3FF79E6F7FF6085 + 8DFF83BFCBFF0261A0900000000000000000025F9C8191D0E6E1B0ECF9FFAEEB + F9FFADEBF9FFACEBF9FFABEAF9FF80D8E9FF32AFC5FF79E6F7FF2C99AEFF80BF + CDFF86CCE5E1025F9C810000000000000000025C9832025C9785025C9799025C + 9799B7EDFDFF025C97990174A3B2018BABE179E6F7FF017895E5016491B4025C + 9799025C9785025C983200000000000000000000000000000000000000000355 + 8BA603558BA6016798570196AFB679E6F7FF017E95BE00728944000000000000 + 000000000000000000000000000000000000000000000000000000000000034D + 7DB5034E7F3D016D917FD9F4FFFF017E95BE0072894400000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000FF014F68AB015F773D0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000C7740200CB770200DB830300E1870308E58A + 0344E68B038AE68B03ACE68B03BBE68B03ACE68B038AE58A0344E1870308DB83 + 0300CB770200C7740200C7740200C7740200CB770200D9820320DB830399E29C + 37CFECC487EBF2D5A6F8F2D9B2FEFCF1CDF8F6DCA5EBE6A645CFDB830399D982 + 0320CB770200C7740200C7740200C7740200C9760220CF7F0FB0E2B36FE6EFD7 + ABFFFCF2CCFFF1D5A5FFEFCE9BFFF8EAC6FFFFFAD7FFFFF9D7FFEDCB8EE6CF7F + 0FB0C9760220C7740200C7740200B5670209BA6A029EDDB06FE7E7C389FFF8E7 + BAFFFEF2CCFFEFD4A5FFF2D9ADFFF8E9C3FFFCF0CAFFFFF5CAFFFFF4C6FFE6C3 + 86E7BA6A029EB5670209B5670200A65C0147B87A2AD5DAA95FFFDFB268FFF4D9 + A1FFE4BE82FFE4BD7DFFF3D8A7FFFFEDBFFFDCB57EFFF4D9A3FFFFE8AEFFFBE3 + ACFFB67525D5A65C0147A35A010097510192CE9D5EEFD79E48FFD8A045FFD8A3 + 4FFFDCAA57FFDEAD5DFFDFB069FFD2A05CFFC9934EFFFAD18FFFEDBF7AFFE0AD + 62FFCE9D5AEF9751019297510100894700B8E8B571FAD49541FFCD8F2FFFD498 + 38FFD49B3BFFD59C3EFFCF953CFFE6AD5EFFFDC577FFF5BB6CFFCE8F3EFFCB8B + 30FFCE984AFA894700B889470000814100C9BC7F38FEE59E43FFC98525FFCD8C + 28FFCE8C29FFCE8D2AFFCB8A29FFCE8A32FFD7903EFFF5AD54FFB9741DFFD48D + 32FFC88C3EFE814100C981410000804000B9CB8A3BFAC88221FFCC8724FFCE8A + 25FFCE8A27FFCE8A27FFCE8A28FFC88425FFDC9036FFF5A546FFB96F1EFFFFAD + 4BFFE9A351FA804000B98040000085430094B8772BF0D28926FFD38B28FFD48E + 2CFFD48F30FFD59132FFD59132FFD18D30FFDC9137FFD1842FFF619B13FF44AA + 0EFF609E19F885430094854300008D480049A35D12DADC9133FFDC9132FFDE95 + 3AFFDF9942FFDF9C47FFE09D48FFDF9B46FFDC9741FFCF8635FF43A812FF75EE + 64FF309A06F86E5E00494F720000964E0009995000A4CA7E28EBE79942FFE9A0 + 4EFFEAA659FFEBAA60FFEBAB63FFEBAA60FF68A023FF3A9B0FFF41A617FF66EB + 55FF259300ED139D00CE129C0099A2570000A4580022AA5D04BAD48732EBF0A8 + 5EFFF2B06BFFF3B473FFF3B576FFF3B473FF3D9B16FF52E741FF52E741FF52E7 + 41FF52E741FF52E741FF109500CCA2570000A5590000B0600022B16100A4C576 + 1CD9E59B4FF0F1AD6AFAF6B475FEF1AD6AFA61901CF72E8805F8258600ED3DE2 + 2CFF0E8C00CC0E8C00CC0E8D0099A2570000A5590000B1610000B6640009B967 + 0049BA670094BA6700B9BA6700C9BA6700B9BA670094B96700490D8300CE2BDF + 1AFF0C8300CC0D8800000E8C0000A2570000A5590000B1610000B6640000BA67 + 0000BC680000BC680000BC680000BC680000BC680000626D0000066D00990569 + 00CC066D0099077100000E8C0000C7740200CB770200DB830300E1870308E58A + 0344E68B038AE68B03ACE68B03BBE68B03ACE68B038AE58A0344E1870308DB83 + 0300CB770200C7740200647F5100C7740200CB770200D9820320DB830399E29C + 37CFECC487EBF2D5A6F8F2D9B2FEFCF1CDF8F6DCA5EBE6A645CFDB830399D982 + 0320CB770200C7740200C7740200C7740200C9760220CF7F0FB0E2B36FE6EFD7 + ABFFFCF2CCFFF1D5A5FFEFCE9BFFF8EAC6FFFFFAD7FFFFF9D7FFEDCB8EE6CF7F + 0FB0C9760220C7740200C7740200B5670209BA6A029EDDB06FE7E7C389FFF8E7 + BAFFFEF2CCFFEFD4A5FFF2D9ADFFF8E9C3FFFCF0CAFFFFF5CAFFFFF4C6FFE6C3 + 86E7BA6A029EB5670209B5670200A65C0147B87A2AD5DAA95FFFDFB268FFF4D9 + A1FFE4BE82FFE4BD7DFFF3D8A7FFFFEDBFFFDCB57EFFF4D9A3FFFFE8AEFFFBE3 + ACFFB67525D5A65C0147A35A010097510192CE9D5EEFD79E48FFD8A045FFD8A3 + 4FFFDCAA57FFDEAD5DFFDFB069FFD2A05CFFC9934EFFFAD18FFFEDBF7AFFE0AD + 62FFCE9D5AEF9751019297510100894700B8E8B571FAD49541FFCD8F2FFFD498 + 38FFD49B3BFFD59C3EFFCF953CFFE6AD5EFFFDC577FFF5BB6CFFCE8F3EFFCB8B + 30FFCE984AFA894700B889470000814100C9BC7F38FEE59E43FFC98525FFCD8C + 28FFCE8C29FFCE8D2AFFCB8A29FFCE8A32FFD7903EFFF5AD54FFB9741DFFD48D + 32FFC88C3EFE814100C981410000804000B9CB8A3BFAC88221FFCC8724FFCE8A + 25FFCE8A27FFCE8A27FFCE8A28FFC88425FFDC9036FFF5A546FFB96F1EFFFFAD + 4BFFE9A351FA804000B98040000085430094B8772BF0D28926FFD38B28FFD48E + 2CFFD48F30FFD59132FFD59132FFD18D30FFDC9137FFD1842FFFE8993BFFFFAC + 47FFDD9543F085430094854300008D480049A35D12DADC9133FFDC9132FFDE95 + 3AFFDF9942FFDF9C47FFE09D48FFDF9B46FFDC9741FFCF8635FFFFB656FFFFB6 + 56FFAE691CDA6A362B4946245400964E0009995000A4CA7E28EBE79942FFE9A0 + 4EFFEAA659FFEBAA60FFEBAB63FFEBAA60FF5D4287FF2C1E95FF33289CFF291E + 95FB150B90ED0201A6CE0000A699A2570000A4580022AA5D04BAD48732EBF0A8 + 5EFFF2B06BFFF3B473FFF3B576FFF3B473FF31248FFF5E5EF7FF5E5EF7FF5E5E + F7FF5E5EF7FF5E5EF7FF000098CCA2570000A5590000B0600022B16100A4C576 + 1CD9E59B4FF0F1AD6AFAF6B475FEF1AD6AFA583B6BF723156EF8190E6EED0503 + 7CD3000080CC000080CC00008499A2570000A5590000B1610000B6640009B967 + 0049BA670094BA6700B9BA6700C9BA6700B9BA670094B9670049633737090000 + 7700000077000000770000008000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00C7740200CB770200DB830300E1870308E58A + 0344E68B038AE68B03ACE68B03BBE68B03ACE68B038AE58A0344E18703089A6D + 2C002B2B9D390101DEAF0101C640C7740200CB770200D9820320DB830399E29C + 37CFECC487EBF2D5A6F8F2D9B2FEFCF1CDF8F6DCA5EBE6A645CFDB830399956A + 2D4038386F7C8080FFFF0101B1C1C7740200C9760220CF7F0FB0E2B36FE6EFD7 + ABFFFCF2CCFFF1D5A5FFEFCE9BFFF8EAC6FFFFFAD7FFFFF9D7FFB1BF97EB8A64 + 2FD2F7F7F7FF1A1A468E00009F46B5670209BA6A029EDDB06FE7E7C389FFF8E7 + BAFFFEF2CCFFEFD4A5FFF2D9ADFFF8E9C3FFFCF0CAFFC2E1C6FF4CB3B6FF79E6 + F7FF5C3E16CE281D103600009C00A65C0147B87A2AD5DAA95FFFDFB268FFF4D9 + A1FFE4BE82FFE4BD7DFFF3D8A7FFFFEDBFFFA9B391FF48ABACFF79E6F7FF4198 + 9BFF846F39DEA65C0147A35A010097510192CE9D5EEFD79E48FFD8A045FFD8A3 + 4FFFDCAA57FFDEAD5DFFDFB069FFA2A377FF3C9693FF79E6F7FF3D8F8EFFA29A + 67FFCE9D5AEF9751019297510100894700B8E8B571FAD49541FFCD8F2FFFD498 + 38FFD49B3BFFD59C3EFFB2924CFF449D98FF79E6F7FF3F8E8AFF95854EFFCB8B + 30FFCE984AFA894700B889470000814100C9BC7F38FEE59E43FFC98525FFCD8C + 28FFCE8C29FFCE8D2AFF667B5DFFD9F4FFFF37837FFFB39C60FFB9741DFFD48D + 32FFC88C3EFE814100C981410000804000B9CB8A3BFAC88221FFCC8724FFCE8A + 25FFCE8A27FFCE8A27FF000000FF446052FFAE8747FFF5A546FFB96F1EFFFFAD + 4BFFE9A351FA804000B98040000085430094B8772BF0D28926FFD38B28FFD48E + 2CFFD48F30FFD59132FFD59132FFD18D30FFDC9137FFD1842FFFE8993BFFFFAC + 47FFDD9543F085430094854300008D480049A35D12DADC9133FFDC9132FFDE95 + 3AFFDF9942FFDF9C47FFE09D48FFDF9B46FFDC9741FFCF8635FFFFB656FFFFB6 + 56FFAE691CDA8D4800498B470000964E0009995000A4CA7E28EBE79942FFE9A0 + 4EFFEAA659FFEBAA60FFEBAB63FFEBAA60FFEAA659FFDA9148FFFFC66EFFDA9A + 44EB995000A4964E0009964E0000A2570000A4580022AA5D04BAD48732EBF0A8 + 5EFFF2B06BFFF3B473FFF3B576FFF3B473FFF2B06BFFE49C59FFDEA754EBAB60 + 07BAA4580022A2570000A2570000A2570000A5590000B0600022B16100A4C576 + 1CD9E59B4FF0F1AD6AFAF6B475FEF1AD6AFAE59B4FF0C3731BD9B16100A4B060 + 0022A5590000A2570000A2570000A2570000A5590000B1610000B6640009B967 + 0049BA670094BA6700B9BA6700C9BA6700B9BA670094B9670049B6640009B161 + 0000A5590000A2570000A2570000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003B7F320015A9000015A9000015A9 + 000015A9000015AA009915AA00CC15AA00CC15AA009915A9000015A9000015A9 + 000015A90000119A0000FFFFFF00FFFFFF00119A0000129F000014A8000014A8 + 000014A8000014A800CC72E961FF71E860FF14A800CC14A8000014A8000014A8 + 0000129F0000119A0000FFFFFF00FFFFFF00119A0000119B0000129E000014A5 + 000014A5000014A500CC69E058FF69E058FF14A500CC14A5000014A50000129E + 0000119B0000119A0000FFFFFF00FFFFFF00119A0000119B0000119B0000129D + 000013A2000013A200CC62D951FF61D850FF13A200CC13A20000129D0000119B + 0000119B0000119A0000FFFFFF00FFFFFF00119A0000119B0000119B0000119B + 0000129C0000129E00CC5AD149FF59D048FF129E00CC129C0000119B0000119B + 0000119B0000119A0000FFFFFF00FFFFFF00119A0099119A00CC119A00CC119A + 00CC119A00CC119A00CC54CB43FF52C941FF119A00CC119A00CC119A00CC119A + 00CC119A00CC119A0099FFFFFF00FFFFFF00109600CC5ED54DFF55CC44FF54CB + 43FF53CA42FF52C941FF4BC23AFF4AC139FF4FC63EFF4EC53DFF4DC43CFF4CC3 + 3BFF4EC53DFF109600CCFFFFFF00FFFFFF000F9200CC59D048FF50C73FFF50C7 + 3FFF4FC63EFF4AC139FF3BB32AFF31A920FF31A920FF2CA51BFF2BA31AFF2DA5 + 1CFF33AB22FF0F9200CCFFFFFF00FFFFFF000E8E00990E8D00CC0E8D00CC0E8D + 00CC0E8D00CC0E8D00CC2DAE1CFF2BAC1AFF0E8D00CC0E8D00CC0E8D00CC0E8D + 00CC0E8D00CC0E8E0099FFFFFF00FFFFFF000E8D00000E8C00000E8C00000E8C + 00000E8B00000D8900CC29B618FF27B416FF0D8900CC0E8B00000E8C00000E8C + 00000E8C00000E8D0000FFFFFF00FFFFFF000E8D00000E8C00000E8C00000E8A + 00000C8400000C8400CC25C014FF24C013FF0C8400CC0C8400000E8A00000E8C + 00000E8C00000E8D0000FFFFFF00FFFFFF000E8D00000E8C00000D8800000A7D + 00000A7D00000A7D00CC23CD12FF22CC11FF0A7D00CC0A7D00000A7D00000D88 + 00000E8C00000E8D0000FFFFFF00FFFFFF000E8D00000C830000066D0000066D + 0000066D0000066D00CC22D811FF22D811FF066D00CC066D0000066D0000066D + 00000C8300000E8D0000FFFFFF00FFFFFF000E8D000003600000036000000360 + 000003600000035F0099025D00CC025D00CC035F009903600000036000000360 + 0000036000000E8D0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000A7990000A8CC0000A8CC0000 + A8CC0000A8CC0000A8CC0000A8CC0000A8CC0000A8CC0000A8CC0000A8CC0000 + A8CC0000A8CC0000A799FFFFFF00FFFFFF0000009ECC6666EEFF5B5BE3FF5555 + DDFF4F4FD7FF4A4AD2FF4545CDFF4343CBFF4141C9FF4040C8FF3F3FC7FF3E3E + C6FF4040C8FF00009ECCFFFFFF00FFFFFF0000008FCC5F5FE7FF5252DAFF4C4C + D4FF4646CEFF4141C9FF3E3EC6FF3D3DC5FF3C3CC4FF3B3BC3FF3A3AC2FF3939 + C1FF3A3AC2FF00008FCCFFFFFF00FFFFFF0000007E99000078CC000078CC0000 + 78CC000078CC000078CC000078CC000078CC000078CC000078CC000078CC0000 + 78CC000078CC00007E99FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010181010101AC010101AC0101 + 01AC010101AC010101AC010101AC010101AC010101AC010101AC010101AC0101 + 01AC01010181FFFFFF00FFFFFF00FFFFFF000101010001010100010101000101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF000101010001010100010101000101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF00010101B501010109010101B50101 + 0109010101B501010109010101B501010109010101B501010109010101B50101 + 0109010101B5FFFFFF00FFFFFF00FFFFFF000101010001010100010101000101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF000101010001010100010101000101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF00010101C3010101C3010101C30101 + 019301010100010101C3010101C3010101C30101010001010193010101C30101 + 01C3010101C3FFFFFF00FFFFFF00FFFFFF000101010001010100010101000101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000FFFFFF00FFFFFF00FFFFFF00000000AA0000000C000000E40000 + 00E4000000E40000000C000000E40000000C000000E4000000E4000000E40000 + 000C000000AAFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000004D0000000D000000670000 + 000D000000670000000D000000670000000D000000670000000D000000330101 + 012B01010181FFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 00000000000000000000000000000000000000000000010101000101012C0101 + 01AE0101012CFFFFFF00FFFFFF00FFFFFF000000006B00000000000000000000 + 000000000000000000000000000001010100010101000101012C010101B00101 + 012C00000036FFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 0000000000000101010001010100010101000101012D010101B30101012D0101 + 01000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 00000101010001010100010101000101012E010101B60101012E010101000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000101 + 010001010100010101000101012F010101B90101012E01010100010101000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF000000007800000000000000000101 + 01000101010001010130010101BC0101012F0101010001010100000000000000 + 000000000078FFFFFF00FFFFFF00FFFFFF000000001000000000010101000101 + 010001010131010101C001010130010101000101010001010100000000000000 + 000000000010FFFFFF00FFFFFF00FFFFFF000000008000000000010101000101 + 0132010101C40101013101010100010101000101010000000000000000000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000010101320101 + 01C7010101320101010001010100010101000101010001010100010101000000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101014500000034010101CC0101 + 0133010101000101010001010100010101000101010001010100010101000101 + 010001010189FFFFFF00FFFFFF00FFFFFF0001010138000000D9010101360101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010113FFFFFF00FFFFFF00FFFFFF00000000AC01010139010101540101 + 0115010101A401010115010101A401010115010101A401010115010101A40101 + 01150101017BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00010101810101012B000000330000 + 000D000000670000000D000000670000000D000000670000000D000000670000 + 000D0000004DFFFFFF00FFFFFF00FFFFFF000101012C010101AE0101012C0101 + 0100000000000000000000000000000000000000000000000000000000000000 + 00000000000DFFFFFF00FFFFFF00FFFFFF00000000360101012C010101B00101 + 012C010101000101010000000000000000000000000000000000000000000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E010101000101012D0101 + 01B30101012D0101010001010100010101000000000000000000000000000000 + 00000000000EFFFFFF00FFFFFF00FFFFFF000000007100000000010101000101 + 012E010101B60101012E01010100010101000101010000000000000000000000 + 000000000071FFFFFF00FFFFFF00FFFFFF000000000F00000000010101000101 + 01000101012E010101B90101012F010101000101010001010100000000000000 + 00000000000FFFFFFF00FFFFFF00FFFFFF000000007800000000000000000101 + 0100010101000101012F010101BC010101300101010001010100000000000000 + 000000000078FFFFFF00FFFFFF00FFFFFF000000001000000000000000000101 + 0100010101000101010001010130010101C00101013101010100010101000000 + 000000000010FFFFFF00FFFFFF00FFFFFF000000008000000000000000000000 + 000001010100010101000101010001010131010101C401010132010101000000 + 000000000080FFFFFF00FFFFFF00FFFFFF000000001100000000010101000101 + 01000101010001010100010101000101010001010132010101C7010101320000 + 000000000011FFFFFF00FFFFFF00FFFFFF000101018901010100010101000101 + 0100010101000101010001010100010101000101010001010133010101CC0000 + 003401010145FFFFFF00FFFFFF00FFFFFF000101011401010100010101000101 + 0100010101000101010001010100010101000101010001010100010101360000 + 00D901010138FFFFFF00FFFFFF00FFFFFF000101017B01010115010101A40101 + 0115010101A401010115010101A401010115010101A401010115010101540101 + 0139000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0001010181010101AC010101AC0101 + 01AC010101AC010101AC010101AC010101AC010101AC010101AC010101AC0101 + 01AC01010181FFFFFF00FFFFFF00FFFFFF000101010001010100010101000101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF000101010001010100010101000101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF00010101B5010101B5010101B50101 + 01B5010101B5010101B5010101B5010101B5010101B5010101B5010101B50101 + 01B5010101B5FFFFFF00FFFFFF00FFFFFF00010101BA010101BA010101BA0101 + 01BA010101BA010101BA010101BA010101BA010101BA010101BA010101BA0101 + 01BA010101BAFFFFFF00FFFFFF00FFFFFF000101010001010100010101000101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF000101010001010100010101000101 + 0100010101000101010001010100010101000101010001010100010101000101 + 010001010100FFFFFF00FFFFFF00FFFFFF00010101C8010101C8010101C80101 + 01C8010101C8010101C8010101C8010101C8010101C8010101C8010101C80101 + 01C8010101C8FFFFFF00FFFFFF00FFFFFF00010101D1010101D1010101D10101 + 01D1010101D1010101D1010101D1010101D1010101D1010101D1010101D10101 + 01D1010101D1FFFFFF00FFFFFF00FFFFFF00000000AA000000E4000000E40000 + 00E4000000E4000000E4000000E4000000E4000000E4000000E4000000E40000 + 00E4000000AAFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000 + 000001535F0001A6BE0001A6BE0051515100515151000101E5000101E5160101 + D1000000B3000000B3000000B300000000000000000000000000003E530001A6 + BE0001A6BE0001A6BE0001A6BE0051515100515151000101E53C0101E1AE0101 + CF870000B3000000B3000000B300003E5300003E5300007CA500007CA50001A6 + BE0001A6BE0001A6BE0001A6BE0051515100505050264141416F7575FEFF4747 + E2E90000AE440000AE000000AE00007CA500007CA500007CA500007CA50001A6 + BE0001A6BE0001A6BE0001A6BE00505050264141416FFDFDFDFFACACACD50000 + AAC40000A5000000A5000000A500007CA500007CA500007CA500007CA50001A6 + BE0001A6BE0001A6BE0001A5BD3F019AB2B452C6D7FF33AABCF0090909880101 + 7C000000A0000000A0000000A000007CA500007CA500007CA500007CA50001A6 + BE0001A6BE0001A5BD3F019AB2B47BE8F9FF50C1D4EA006F86C3041E24000202 + 52000000A0000000A0000000A000007CA500007CA500007CA500007CA50001A6 + BE0001A5BD3F019AB2B47BE8F9FF50C1D4EA006F86C3006A8000023641000202 + 52000000A0000000500000000000007CA500007CA500007CA500007CA50001A5 + BD3F019AB2B47BE8F9FF50C1D4EA006F86C3006A800000687E00023641000101 + 290000000000000000000000000000749A0000749A0000759C000078A01E0D7A + 9D7D66DDEEFF34A2B6E8006F86C3006A800000687E0000343F00000000000000 + 0000000000000000000000000000006C8F00006C8F00006E9201016C8F82CCEE + FFFF015672A00150697A01647B0000343F000000000000000000000000000000 + 000000000000000000000000000001688900016889000165868CA6D5E6FF0152 + 6CA7013B4E490127340000000000000000000000000000000000000000000000 + 00000000000000000000000000004D33800000000000000000FF014F68AA013B + 4E2B00000077000000EA000000D9000000C3000000AA0000008D0000006F0000 + 0052000000370000001E0000000C9966FF009865FF004B3280004B58B300925F + FF00482F8000472D8000452C8000442B80004329800041288000402780003F26 + 80003E2580003D2480003C2380009966FF009865FFFF9663FFFF9461FFFF925F + FFFF905DFFFF8D5AFFFF8A57FFFF8855FFFF8552FFFF824FFFFF804DFFFF7E4B + FFFF7C49FFFF7A47FFFF7845FFC09966FFFF9865FFFF9663FFFF9461FFFF925F + FFFF905DFFFF8D5AFFFF8A57FFFF8855FFFF8552FFFF824FFFFF804DFFFF7E4B + FFFF7C49FFFF7A47FFFF7845FFFF9966FF009865FFFF9663FFFF9461FFFF925F + FFFF905DFFFF8D5AFFFF8A57FFFF8855FFFF8552FFFF824FFFFF804DFFFF7E4B + FFFF7C49FFFF7A47FFFF7845FFC0FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000004D0000000D000000670000 + 000D000000670000000D000000670000000D000000670000000D000000670000 + 000D0000004DFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000000000000000000000000000D000000000000000000000000000000000000 + 000000000013FFFFFF00FFFFFF00FFFFFF000000006B00000000000000000000 + 000000000000000000000000006B000000000101650001013000000000000000 + 00000000006BFFFFFF00FFFFFF00FFFFFF000000000E00000000000000000000 + 000001525E002B2B2B0016164F0E0101A9000101C9000101BD00000000000000 + 000000000024FFFFFF00FFFFFF00FFFFFF000000007100000000000000000000 + 000001A3BB00555555002B2B9D390101DEAF0101C6400101BD00010101000000 + 000000000073FFFFFF00FFFFFF00FFFFFF000000000F00000000000000000000 + 000001A3BB005454542438386F7C8080FFFF0101B1C101015600010101000101 + 01000101013CFFFFFF00FFFFFF00FFFFFF00000000780000000F000000780129 + 2F0F01A2BA3F4A4A4A6CF7F7F7FF1A1A468E00009F460101012E0101015A0101 + 015901010183FFFFFF00FFFFFF00FFFFFF000000001001292F0001525E0001A2 + BA3F0197B0B579E6F7FF2222227D1212122E00009C0001010100010101000101 + 01000101015EFFFFFF00FFFFFF00FFFFFF000000008001525E0001A2BA3F0197 + B0B579E6F7FF017E95BE053E49410808080001014F0001010100010101000101 + 01000101019BFFFFFF00FFFFFF00FFFFFF0000202B1101A2BA3F0197B0B579E6 + F7FF017E95BE0072894401010151010101000101010001010100010101000101 + 010001010189FFFFFF00FFFFFF00FFFFFF00007EA7260197B0B579E6F7FF017E + 95BE0072894401394400010101B5010101000101010000000000010101000101 + 0100010101B9FFFFFF00FFFFFF00FFFFFF00016D917FD9F4FFFF017E95BE0056 + 6744001C220000000000000000D0000000000000000000000000000000000000 + 0000000000C2FFFFFF00FFFFFF00FFFFFF00000000FF014F68AB015F773D0000 + 0074000000E6000000E6000000E6000000E6000000E6000000E6000000E60000 + 00E6000000ACFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF008AA8 + BF427EABC6BD78B3CDED7BB8D0FA7AB4CDFA71A9C4E8719DB9B07A99B039FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0086AAC29678BA + D2F9C8D9E3FFDDE7EAFFEEF1F1FFECF0F0FFD2E0E4FFA8C4D2FF679CB8F46C8F + A97DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0085A8C09197CCDCFFE1EB + EEFFEEE1D9FFDFBEACFFD5AD96FFD4AA92FFDCB7A3FFE8DACEFFC6D9DFFF689B + B6FF64859F75FFFFFF00FFFFFF00FFFFFF0088A3B93C74B3CCFADFE9ECFFE6CF + C2FFDFBFAEFFF1E3DCFFF3F1ECFFF4F1EBFFF1E2D9FFDCBAA3FFDEC1AFFFB7CF + D8FF5883A4F56A869B31FFFFFF00FFFFFF0077A1BCB6B7CFDBFFEDE0D7FFDEBD + AAFFFFFFFFFFF0F0EEFFE7E5DAFFFFFFF7FFFFFFF7FFFFFEF3FFDCB498FFE1D1 + C4FF73A4BBFF597C98A3FFFFFF00FFFFFF006DA2BEE7D3E1E6FFDBB9A4FFF1E3 + D6FFFEFBF5FFF5F5F3FF9F9E95FFF0F0E9FFF8F8F2FFBEB9ADFFF0DAC2FFD1A7 + 8BFFA9CAD3FF537B9BDFFFFFFF00FFFFFF006CA1BDF7E4ECEEFFD1A58AFFFAF6 + E9FFFDF8EEFFFFFFF9FF818079FFB1AEA4FF817F77FFC9C6BAFFFAF0D3FFC995 + 72FFC9DFE2FF547B9EF6FFFFFF00FFFFFF00679AB8F7DDEAECFFCF9F81FFFAF3 + E2FFFDF6E9FFF2F0E3FF8D8C84FF817F77FFD2CFC2FFFFFBEBFFFAECCCFFC790 + 6DFFC1DDE1FF53799DF6FFFFFF00FFFFFF005E8EADDEB7D3DDFFD1AA90FFF0DB + C1FFFFF7E6FFFAF2E3FFC5C0B6FFF1EDDEFFFFFCE8FFFFF5DFFFEFD4AFFFC99B + 7BFF92C2D0FF507595E2FFFFFF00FFFFFF005E85A09F78A9C0FFDAD1C6FFD9AA + 88FFFFFEEBFFFFFAEEFFFFFDF2FFFFFEF2FFFFFCEFFFFFFDEBFFD9A37AFFCBC6 + B9FF5894B1FF547490AAFFFFFF00FFFFFF006B879D305782A2F6A2CCD8FFCDB7 + A5FFD8AA89FFEFDFCFFFFAF6F3FFFAF5F3FFEFDFD1FFD7A785FFC3AC98FF82BD + CEFF4D7194F7627B9135FFFFFF00FFFFFF00FFFFFF0061819A785588A6FF96C8 + D6FFCCCABFFFC89F86FFC59276FFC49073FFC49A80FFC3C4B9FF7DBDCDFF4777 + 98FF5A778F80FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005D7C957D5078 + 9AF35A97B1FF85BDCEFFA4D6DEFFA0D5DEFF7BB9CBFF4F8CABFF4D7294F45976 + 8F82FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00617D + 9536537591A74E7293E14D7497F64D7497F64E7293E1527490A95E7A9137FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0086C38BF582C0870EFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0084C28AF596CD9BFF80BE85FF79B97E0EFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0083C188F594CD9AFFB3E2B7FF93CB98FF77B77CFF70B2 + 740EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0082C087F594CC99FFB2E2B7FFA3DCAAFFB0E0B6FF8CC692FF6EB1 + 73FF66AB6B0EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0081BF86F593CC98FFB1E1B7FFA3DBA9FF9BD8A2FF73B477FFAFDFB4FF87C3 + 8CFF65AA69FF5DA4610EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF007FBE + 85F592CB97FFB1E1B6FF85C38AFF80C185FF99D7A0FF98D79FFF9FD9A5FFACDF + B2FF7DBB81FF58A05CF6FFFFFF00FFFFFF00FFFFFF00FFFFFF007EBD83F691CA + 96FFB1E0B6FFD9F3DDFFF7FCF8FFA4D0A7FF7EC084FF9FD9A5FFACDEB2FF7BBB + 80FF569F5AFBFFFFFF00FFFFFF00FFFFFF008EC993257DBC82FA90C995FFB0E0 + B6FF85C28AFFF7FCF8FF95C297FFDDEEDFFF82C287FFABDEB1FF7BBA7FFF58A0 + 5CFF59A15DFF539C5704FFFFFF008DC9937D7DBB82FF8FC894FFB0E0B6FFA2DA + A8FF7FC185FFA4D0A7FFDDEEDFFF80B883FFABDEB1FF7AB97FFF569F5AFFC4E7 + C8FF78B87CFF4E995284FFFFFF007BBB80FF8EC893FFAFDFB5FFA1DAA7FF98D7 + 9FFF97D69EFF7EC083FF82C187FFABDDB0FF79B97DFF63AE67FFC4E7C8FFC1E4 + C4FFB9E0BEFF4F9A53FF459249117FBD84A07FBD84FF97CE9CFFADDFB3FF6FB3 + 74FF96D59DFF9DD8A3FFAADDB0FF78B87CFF72BA76FFC3E7C8FFB2DAB5FF69B8 + 6EF8569E59FF45914873418F44327FBE84197BBB80FF77B77CFF91CB97FFABDE + B1FF9CD7A2FFAADDB0FF77B77CFF60AC65FFAED8B2FF8BC491FF4C9750B94894 + 4C9144914822FFFFFF00FFFFFF00FFFFFF0075B67A9B9CCDA0FF6FB273FF8DC7 + 92FFAADCAFFF76B67BFF519B55FF77B77BFF509A53DD4B964F4247934B29FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006FB274277CBB81FCB7DEBBFF67AC + 6CFF75B67AFF4E9851FE539C57B84F99537AFFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006AAE6E0565AA69AF60A665FD6BAE + 6FFF4C9750FB529C56344E995222FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0060A664315BA25FCC569F + 5A4BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FCDEC102FADCBF97F9D9 + BBE3F6D6B8FDF4D3B4FDF1CFAFE3EECBAB97EBC6A602FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FCDEC002FADBBEC0F9E2CDFFFAEC + DEFFF9EEE2FFF9EDE2FFF8E9DAFFF0D5BDFFE7C09FC0E3BC9A02FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FADBBD97F8E2CCFFFAEEE3FFF7E7 + D6FFF6E2CEFFF6E1CBFFF6E3D0FFF9EADDFFECCFB5FFDFB69397FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F7D7B9E3F9EBDEFFF7E7D6FFF6E1 + CCFFF5E0CAFFF5DEC8FFF5DDC5FFF6E1CBFFF5E2D0FFDBB08CE3FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F4D3B4FDF9EDE1FFF6E1CCFFF5DF + C9FFF5DEC7FFF4DCC4FFF4DBC2FFF4DAC0FFF8E7D6FFD7AA86FDFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F0CEAEFDF9ECDFFFF5DFC8FFF5DD + C6FFF4DCC3FFF4DAC1FFF3D9BEFFF3D7BDFFF8E6D3FFD3A57FFDFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00ECC8A8E3F7E7D7FFF6E1CCFFF4DB + C2FFF4DAC0FFF3D8BDFFF3D7BBFFF4DBC2FFF3DEC9FFCD9F7BE7FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E8C3A297EDD0B7FFF8E8D9FFF5DE + C8FFF3D8BDFFF3D6BBFFF4DBC2FFF7E4D2FFDFBB9DFF9D9492F74B84BC27FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E4BD9B02E1B896C0E8C9AEFFF5E1 + CDFFF7E5D3FFF7E5D1FFF3DDC8FFDFBA9CFFC7A891FF86AED5FF417DB5EB3977 + AF27FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00DDB28F02D9AE8A97D6A9 + 85E3D3A57FFDD0A07BFDCD9C76E4A2938ADE75A2CCFFABCBE8FF76A4CEFF3070 + A8EB286BA327FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00447FB7063C79B1AD6497C5FF9DC1E4FF6699 + C7FF1F659DEBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003272AA062B6DA5AD558DBCFF89B5 + DDFF185F97FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0022669E061B629AAD2267 + 9DFF115B9387FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00145D9503105A + 921AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000001C00000033000000360000 + 0036000000360000003600000036000000360000003600000036000000200000 + 0002FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000033F8F8F8F0FBFBFBFDFCFC + FCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFF8F8F8FF949494910000 + 002000000002FFFFFF00FFFFFF00FFFFFF0000000036FBFBFBFDF4F4F4FFF5F5 + F5FFF5F5F5FFF5F5F5FFF1F1F1FFEFEFEFFFE9E9E9FFFCFCFCFFE7E7E7FF9595 + 95910000002000000002FFFFFF000000000100000036FCFCFCFFF7F7F7FFF9F9 + F9FFF7F7F7FFF7F7F7FFF3F3F3FFF0F0F0FFEAEAEAFFFCFCFCFFF6F6F6FFF4F4 + F4FF9999999100000020FFFFFF000000000100000036FCFCFCFFF9F9F9FFF9F9 + F9FFF9F9F9FFF7F7F7FFF6F6F6FFF2F2F2FFEBEBEBFFFCFCFCFFFCFCFCFFFCFC + FCFFFCFCFCFF00000036000000010000000100000036FCFCFCFFFBFBFBFFFCFC + FCFFFCFCFCFFFBFBFBFFF8F8F8FFF5F5F5FFF1F1F1FFECECECFFEAEAEAFFE6E6 + E6FFFCFCFCFF00000036000000010000000100000036FCFCFCFFFCFCFCFFFCFC + FCFFFCFCFCFFFCFCFCFFFBFBFBFFF8F8F8FFF5F5F5FFF2F2F2FFEFEFEFFFEDED + EDFFFCFCFCFF00000036000000010000000100000036FCFCFCFFFCFCFCFFFCFC + FCFFFCFCFCFFFCFCFCFFFCFCFCFFFBFBFBFFF8F8F8FFF6F6F6FFF3F3F3FFF2F2 + F2FFFCFCFCFF00000036000000010000000100000036FCFCFCFFFCFCFCFFFCFC + FCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFAFAFAFFF9F9F9FFF6F6F6FFF6F6 + F6FFFCFCFCFF00000036000000010000000100000036FCFCFCFFFCFCFCFFFCFC + FCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFBFBFBFFF9F9F9FFF9F9F9FFF8F8 + F8FFFCFCFCFF00000036000000010000000100000036FCFCFCFFFCFCFCFFFCFC + FCFFFCFCFCFFFBFBFBFFFBFBFBFFFBFBFBFFFAFAFAFFFAFAFAFFF8F8F8FFF8F8 + F8FFFCFCFCFF00000036000000010000000100000036FCFCFCFFFCFCFCFFFCFC + FCFFFCFCFCFFFBFBFBFFFBFBFBFFFAFAFAFFFAFAFAFFFAFAFAFFFAFAFAFFFAFA + FAFFFCFCFCFF00000036000000010000000100000036FCFCFCFFFCFCFCFFFCFC + FCFFFCFCFCFFFCFCFCFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFB + FBFFFCFCFCFF00000036000000010000000100000036FCFCFCFEFCFCFCFFFCFC + FCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFC + FCFFFCFCFCFD00000036FFFFFF00FFFFFF0000000034F9F9F9F5FCFCFCFDFCFC + FCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFC + FCFDF9F9F9F300000033FFFFFF00FFFFFF000000001D00000034000000360000 + 0036000000360000003600000036000000360000003600000036000000360000 + 0036000000330000001DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B32C0300B52D0300B82F0300B92F + 0318BA300364BA30039ABA3003B6BA3003B6BA30039ABA300364B92F0318B82F + 0300B52D0300B32C0300FFFFFF00FFFFFF00B32C0300B52D0300B82F0348BD38 + 0DB3D96841DAED8B67F1F49673FCF49572FCED8966F1D8663FDABD380DB3B82F + 0348B52D0300B32C0300FFFFFF00FFFFFF00B32C0300B52D0348C03E15C2ED8A + 67F3EB8765FFD87250FFD87250FFD87250FFD87250FFEA8765FFEA8662F3BF3D + 14C2B52D0348B32C0300FFFFFF00FFFFFF00B22C0319B8350DB4E98664F3E07B + 59FFD26C4AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA8E74FFE07B59FFE37E + 5AF3B7340CB4B22C0319FFFFFF00FFFFFF00AF2A0365D1613CDBDC7856FFD670 + 4EFFD16B49FFD5A291FFD5A291FFE6C2B6FFFFFFFFFFE0AD9CFFD6704EFFDA75 + 53FFC95732DBAF2A0365FFFFFF00FFFFFF00AB27029DDD7956F2CF6947FFCF69 + 47FFCF6947FFCA6442FFC05937FFC28875FFCCCCCCFFBC8977FFAD4624FFB04A + 27FFC15936F2AB27029DFFFFFF00FFFFFF00A72502B9DD7B59FCCC6644FFC962 + 40FFBD5431FFB54B27FFBD735AFFD1CFCFFFC7AEA5FFB24926FFB44A26FFB44A + 26FFBD5431FCA72502B9FFFFFF00FFFFFF00A32302BAD97755FDC85F3BFFC052 + 2CFFBE502AFFB94E28FFDBDBDBFFDBDBDBFFBA4E29FFBE502AFFBE502AFFBE50 + 2AFFC2552FFDA32302BAFFFFFF00FFFFFF009F20029ED06542F3CB5930FFCB58 + 2FFFCB582FFFCB582FFFBC4F29FFBC4F29FFCB582FFFCB582FFFCB582FFFCB58 + 2FFFC5502AF39F20029EFFFFFF00FFFFFF009B1E0268BD4725DDD96338FFD860 + 35FFD86035FFCD5930FFEEEEEEFFEEEEEEFFCD5930FFD86035FFD86035FFD860 + 35FFB83D1ADE9B1E0268FFFFFF00FFFFFF00971B02199C2108B8DA6138F4E668 + 3AFFE5673AFFD75F34FFEEEEEEFFEEEEEEFFD75F34FFE5673AFFE5673AFFD85B + 31F49C2006B8971B0219FFFFFF00FFFFFF00951A02009218024A9D240BC7E162 + 36F4F16F3FFFF16F3EFFCF5A31FFCF5A31FFF16F3EFFF16F3EFFE06034F49D23 + 0AC79218024A951A0200FFFFFF00FFFFFF00951A020090170200820F014B8915 + 06BCB83D20E1E36136F4F57040FDF57040FDE36136F4B83D20E1891506BC820F + 014B90170200951A0200FFFFFF00FFFFFF00951A020090170200800E01007506 + 001A7205006B720500A5720500C3720500C3720500A57205006B7506001A800E + 010090170200951A0200FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00 + } + end + object MainMenu: TMainMenu + Images = ImageList + left = 176 + top = 376 + object MnuFile: TMenuItem + Caption = 'File' + object MnuFileNew: TMenuItem + Action = AcFileNew + end + object MnuFileOpen: TMenuItem + Action = AcFileOpen + end + object MnuFileReopen: TMenuItem + Caption = 'Recently opened files' + end + object MenuItem50: TMenuItem + Caption = '-' + end + object MnuFileSaveAs: TMenuItem + Action = AcFileSaveAs + end + object MenuItem49: TMenuItem + Caption = '-' + end + object MnuFileExit: TMenuItem + Action = AcFileExit + end + end + object MnuEdit: TMenuItem + Caption = 'Edit' + object MenuItem101: TMenuItem + Action = AcCopyToClipboard + end + object MenuItem100: TMenuItem + Action = AcCutToClipboard + end + object MenuItem2: TMenuItem + Action = AcPasteAllFromClipboard + end + object MenuItem4: TMenuItem + Action = AcPasteValueFromClipboard + end + object MenuItem3: TMenuItem + Action = AcPasteFormulaFromClipboard + end + object MenuItem90: TMenuItem + Action = AcPasteFormatFromClipboard + end + object MenuItem98: TMenuItem + Caption = '-' + end + object MenuItem132: TMenuItem + Action = AcSearch + end + object MenuItem92: TMenuItem + Caption = '-' + end + object MenuItem91: TMenuItem + Action = AcSort + end + object MenuItem93: TMenuItem + Action = AcSortColAsc + end + end + object MenuItem51: TMenuItem + Caption = 'Worksheet' + object MenuItem161: TMenuItem + Action = AcAddWorksheet + end + object MenuItem162: TMenuItem + Action = AcDeleteWorksheet + end + object MenuItem163: TMenuItem + Caption = '-' + end + object MenuItem160: TMenuItem + Action = acRenameWorksheet + end + object MenuItem165: TMenuItem + Caption = '-' + end + object MenuItem164: TMenuItem + Action = AcWorksheetRTL + AutoCheck = True + end + end + object MenuItem166: TMenuItem + Caption = 'Row' + object MenuItem167: TMenuItem + Action = AcRowAdd + end + object MenuItem168: TMenuItem + Action = AcRowDelete + end + object MenuItem174: TMenuItem + Caption = '-' + end + object MenuItem175: TMenuItem + Action = AcFrozenRows + AutoCheck = True + end + object MenuItem177: TMenuItem + Caption = '-' + end + object MenuItem99: TMenuItem + Action = AcRowHeight + end + object MenuItem176: TMenuItem + Action = AcAutoRowHeights + end + end + object MenuItem169: TMenuItem + Caption = 'Column' + object MenuItem170: TMenuItem + Action = AcColAdd + end + object MenuItem171: TMenuItem + Action = AcColDelete + end + object MenuItem173: TMenuItem + Caption = '-' + end + object MenuItem172: TMenuItem + Action = AcFrozenCols + AutoCheck = True + end + object MenuItem103: TMenuItem + Caption = '-' + end + object MenuItem102: TMenuItem + Action = AcColWidth + end + end + object MnuFormat: TMenuItem + Caption = 'Cell' + object MenuItem89: TMenuItem + Action = AcBackgroundColorDialog + end + object MenuItem68: TMenuItem + Caption = 'Font' + object MenuItem69: TMenuItem + Action = AcCellFontDialog + end + object MenuItem70: TMenuItem + Caption = '-' + end + object MenuItem71: TMenuItem + Action = AcFontBold + AutoCheck = True + end + object MenuItem72: TMenuItem + Action = AcFontItalic + AutoCheck = True + end + object MenuItem73: TMenuItem + Action = AcFontUnderline + AutoCheck = True + end + object MenuItem74: TMenuItem + Action = AcFontStrikeout + AutoCheck = True + end + end + object MenuItem76: TMenuItem + Caption = 'Text rotation' + object MenuItem77: TMenuItem + Action = AcTextRotHor + AutoCheck = True + end + object MenuItem78: TMenuItem + Caption = '-' + end + object MenuItem79: TMenuItem + Action = AcTextRot90CW + AutoCheck = True + end + object MenuItem80: TMenuItem + Action = AcTextRot90CCW + AutoCheck = True + end + object MenuItem81: TMenuItem + Action = AcTextRotStacked + AutoCheck = True + end + end + object MenuItem75: TMenuItem + Caption = 'Horizontal text alignment' + object MenuItem82: TMenuItem + Action = AcHorAlignLeft + AutoCheck = True + end + object MenuItem83: TMenuItem + Action = AcHorAlignCenter + AutoCheck = True + end + object MenuItem84: TMenuItem + Action = AcHorAlignRight + AutoCheck = True + end + end + object MenuItem85: TMenuItem + Caption = 'Vertical text alignment' + object MenuItem86: TMenuItem + Action = AcVertAlignTop + AutoCheck = True + end + object MenuItem87: TMenuItem + Action = AcVertAlignCenter + AutoCheck = True + end + object MenuItem88: TMenuItem + Action = AcVertAlignBottom + AutoCheck = True + end + end + object MenuItem10: TMenuItem + Caption = 'Number format' + object MenuItem122: TMenuItem + Action = AcNumFormatCustom + AutoCheck = True + end + object MenuItem121: TMenuItem + Caption = '-' + end + object MenuItem55: TMenuItem + Action = AcNumFormatGeneral + AutoCheck = True + end + object MenuItem54: TMenuItem + Caption = '-' + end + object MenuItem12: TMenuItem + Action = AcNumFormatFixed + AutoCheck = True + end + object MenuItem11: TMenuItem + Action = AcNumFormatFixedTh + AutoCheck = True + end + object MenuItem13: TMenuItem + Caption = '-' + end + object MenuItem117: TMenuItem + Action = AcNumFormatFraction1 + AutoCheck = True + end + object MenuItem116: TMenuItem + Action = AcNumFormatFraction2 + AutoCheck = True + end + object MenuItem115: TMenuItem + Action = AcNumFormatFraction3 + AutoCheck = True + end + object MenuItem114: TMenuItem + Caption = '-' + end + object MenuItem53: TMenuItem + Action = AcNumFormatExp + AutoCheck = True + end + object MenuItem14: TMenuItem + Action = AcNumFormatPercentage + AutoCheck = True + end + object MenuItem15: TMenuItem + Caption = '-' + end + object MenuItem17: TMenuItem + Action = AcNumFormatCurrency + AutoCheck = True + end + object MenuItem16: TMenuItem + Action = AcNumFormatCurrencyRed + AutoCheck = True + end + object MenuItem56: TMenuItem + Caption = '-' + end + object MenuItem57: TMenuItem + Action = AcNumFormatDateTime + AutoCheck = True + end + object MenuItem58: TMenuItem + Caption = '-' + end + object MenuItem59: TMenuItem + Action = AcNumFormatLongDate + AutoCheck = True + end + object MenuItem60: TMenuItem + Action = AcNumFormatShortDate + AutoCheck = True + end + object MenuItem61: TMenuItem + Caption = '-' + end + object MenuItem62: TMenuItem + Action = AcNumFormatLongTime + AutoCheck = True + end + object MenuItem63: TMenuItem + Action = AcNumFormatShortTime + AutoCheck = True + end + object MenuItem64: TMenuItem + Action = AcNumFormatLongTimeAM + AutoCheck = True + end + object MenuItem65: TMenuItem + Action = AcNumFormatShortTimeAM + AutoCheck = True + end + object MenuItem66: TMenuItem + Caption = '-' + end + object MenuItem67: TMenuItem + Action = AcNumFormatTimeInterval + AutoCheck = True + end + object MenuItem144: TMenuItem + Caption = '-' + end + object MenuItem145: TMenuItem + Action = AcNumFormatText + AutoCheck = True + end + end + end + object MnuView: TMenuItem + Caption = 'View' + object MenuItem134: TMenuItem + Action = AcShowGridLines + AutoCheck = True + end + object MenuItem135: TMenuItem + Action = AcShowHeaders + AutoCheck = True + end + object MenuItem133: TMenuItem + Caption = '-' + end + object MnuZoom: TMenuItem + Caption = 'Zoom' + object MenuItem148: TMenuItem + Action = AcZoom30 + end + object MenuItem149: TMenuItem + Action = AcZoom50 + end + object MenuItem150: TMenuItem + Action = AcZoom75 + end + object MenuItem146: TMenuItem + Action = AcZoom90 + end + object MenuItem153: TMenuItem + Caption = '-' + end + object MenuItem151: TMenuItem + Action = AcZoom100 + end + object MenuItem154: TMenuItem + Caption = '-' + end + object MenuItem152: TMenuItem + Action = AcZoom150 + end + object MenuItem155: TMenuItem + Action = AcZoom200 + end + object MenuItem156: TMenuItem + Action = AcZoom300 + end + object MenuItem157: TMenuItem + Action = AcZoom500 + end + end + object MenuItem147: TMenuItem + Caption = '-' + end + object MenuItem52: TMenuItem + Action = AcViewInspector + AutoCheck = True + end + end + object MnuSettings: TMenuItem + Caption = 'Settings' + object MenuItem109: TMenuItem + Action = AcSettingsFormatSettings + end + object MenuItem107: TMenuItem + Action = AcSettingsCSVParams + end + object MenuItem108: TMenuItem + Action = AcSettingsCurrency + end + end + object MnuHelp: TMenuItem + Caption = 'Help' + object MenuItem1: TMenuItem + Action = AcAbout + end + end + end + object PuNumFormat: TPopupMenu + left = 504 + top = 216 + object MenuItem19: TMenuItem + Action = AcNumFormatGeneral + AutoCheck = True + end + object MenuItem18: TMenuItem + Caption = '-' + end + object MenuItem6: TMenuItem + Action = AcNumFormatFixed + AutoCheck = True + end + object MenuItem5: TMenuItem + Action = AcNumFormatFixedTh + AutoCheck = True + end + object MenuItem20: TMenuItem + Caption = '-' + end + object MenuItem112: TMenuItem + Action = AcNumFormatFraction1 + AutoCheck = True + end + object MenuItem110: TMenuItem + Action = AcNumFormatFraction2 + AutoCheck = True + end + object MenuItem113: TMenuItem + Action = AcNumFormatFraction3 + AutoCheck = True + end + object MenuItem111: TMenuItem + Caption = '-' + end + object MenuItem21: TMenuItem + Action = AcNumFormatExp + AutoCheck = True + end + object MenuItem123: TMenuItem + Caption = '-' + end + object MenuItem124: TMenuItem + Action = AcNumFormatCustom + AutoCheck = True + end + end + object PuCurrencyFormat: TPopupMenu + left = 504 + top = 280 + object MenuItem7: TMenuItem + Action = AcNumFormatCurrency + AutoCheck = True + end + object MenuItem8: TMenuItem + Action = AcNumFormatCurrencyRed + AutoCheck = True + end + object MenuItem125: TMenuItem + Caption = '-' + end + object MenuItem126: TMenuItem + Action = AcNumFormatCustom + AutoCheck = True + end + end + object PuDateFormat: TPopupMenu + left = 504 + top = 344 + object MenuItem22: TMenuItem + Action = AcNumFormatDateTime + AutoCheck = True + end + object MenuItem23: TMenuItem + Caption = '-' + end + object MenuItem24: TMenuItem + Action = AcNumFormatLongDate + AutoCheck = True + end + object MenuItem25: TMenuItem + Action = AcNumFormatShortDate + AutoCheck = True + end + object MenuItem118: TMenuItem + Caption = '-' + end + object MenuItem119: TMenuItem + Action = AcNumFormatDayMonth + AutoCheck = True + end + object MenuItem120: TMenuItem + Action = AcNumFormatMonthYear + AutoCheck = True + end + object MenuItem127: TMenuItem + Caption = '-' + end + object MenuItem128: TMenuItem + Action = AcNumFormatCustom + AutoCheck = True + end + end + object PuTimeFormat: TPopupMenu + left = 504 + top = 408 + object MenuItem26: TMenuItem + Action = AcNumFormatLongTime + AutoCheck = True + end + object MenuItem27: TMenuItem + Action = AcNumFormatShortTime + AutoCheck = True + end + object MenuItem28: TMenuItem + Caption = '-' + end + object MenuItem29: TMenuItem + Action = AcNumFormatLongTimeAM + AutoCheck = True + end + object MenuItem30: TMenuItem + Action = AcNumFormatShortTimeAM + AutoCheck = True + end + object MenuItem129: TMenuItem + Caption = '-' + end + object MenuItem130: TMenuItem + Action = AcNumFormatCustom + AutoCheck = True + end + end + object PuBorders: TPopupMenu + Images = ImageList + left = 504 + top = 160 + object MenuItem41: TMenuItem + Action = AcCellBorderNone + end + object MenuItem40: TMenuItem + Caption = '-' + end + object MenuItem31: TMenuItem + Action = AcCellBorderTop + end + object MenuItem32: TMenuItem + Action = AcCellBorderInnerHor + end + object MenuItem33: TMenuItem + Action = AcCellBorderBottom + end + object MenuItem43: TMenuItem + Action = AcCellBorderBottomThick + end + object MenuItem44: TMenuItem + Action = AcCellBorderBottomDbl + end + object MenuItem48: TMenuItem + Action = AcCellBorderAllHor + end + object MenuItem36: TMenuItem + Caption = '-' + end + object MenuItem34: TMenuItem + Action = AcCellBorderLeft + end + object MenuItem37: TMenuItem + Action = AcCellBorderInnerVert + end + object MenuItem35: TMenuItem + Action = AcCellBorderRight + end + object MenuItem47: TMenuItem + Action = AcCellBorderAllVert + end + object MenuItem38: TMenuItem + Caption = '-' + end + object MenuItem142: TMenuItem + Action = AcCellBorderDiagUp + end + object MenuItem141: TMenuItem + Action = AcCellBorderDiagDown + end + object MenuItem143: TMenuItem + Caption = '-' + end + object MenuItem39: TMenuItem + Action = AcCellBorderAllOuter + end + object MenuItem42: TMenuItem + Action = AcCellBorderAllOuterThick + end + object MenuItem45: TMenuItem + Caption = '-' + end + object MenuItem46: TMenuItem + Action = AcCellBorderAll + end + end + object PuPaste: TPopupMenu + left = 504 + top = 471 + object MenuItem9: TMenuItem + Action = AcPasteAllFromClipboard + end + object MenuItem94: TMenuItem + Caption = '-' + end + object MenuItem95: TMenuItem + Action = AcPasteValueFromClipboard + end + object MenuItem96: TMenuItem + Action = AcPasteFormatFromClipboard + end + object MenuItem97: TMenuItem + Action = AcPasteFormulaFromClipboard + end + end + object PuRecentFiles: TPopupMenu + left = 504 + top = 536 + end +end diff --git a/applications/spready/smain.pas b/applications/spready/smain.pas new file mode 100644 index 000000000..c0a2d5803 --- /dev/null +++ b/applications/spready/smain.pas @@ -0,0 +1,1198 @@ +unit smain; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, mrumanager, Forms, Controls, Graphics, Dialogs, + ExtCtrls, ComCtrls, ActnList, Menus, StdActns, Buttons, fpstypes, + fpspreadsheet, fpspreadsheetctrls, fpspreadsheetgrid, fpsActions, + fpsRegFileFormats, fpsSYLK, xlsxml, Grids, Types; + +type + + { TMainForm } + + TMainForm = class(TForm) + AcRowDelete: TAction; + AcColDelete: TAction; + AcRowAdd: TAction; + AcColAdd: TAction; + AcSettingsCSVParams: TAction; + AcSettingsCurrency: TAction; + AcSettingsFormatSettings: TAction; + AcSearch: TAction; + AcShowGridLines: TAction; + AcShowHeaders: TAction; + AcFrozenRows: TAction; + AcFrozenCols: TAction; + AcAutoRowHeights: TAction; + AcFileNew: TAction; + AcAbout: TAction; + AcSort: TAction; + AcSortColAsc: TAction; + AcRowHeight: TAction; + AcColWidth: TAction; + AcWorksheetRTL: TAction; + AcViewInspector: TAction; + ActionList: TActionList; + AcFileExit: TFileExit; + AcFileOpen: TFileOpen; + AcFileSaveAs: TFileSaveAs; + ImageList: TImageList; + MainMenu: TMainMenu; + MenuItem1: TMenuItem; + MenuItem102: TMenuItem; + MenuItem103: TMenuItem; + MenuItem160: TMenuItem; + MenuItem161: TMenuItem; + MenuItem162: TMenuItem; + MenuItem163: TMenuItem; + MenuItem164: TMenuItem; + MenuItem165: TMenuItem; + MenuItem166: TMenuItem; + MenuItem167: TMenuItem; + MenuItem168: TMenuItem; + MenuItem169: TMenuItem; + MenuItem170: TMenuItem; + MenuItem171: TMenuItem; + MenuItem172: TMenuItem; + MenuItem173: TMenuItem; + MenuItem174: TMenuItem; + MenuItem175: TMenuItem; + MenuItem176: TMenuItem; + MenuItem177: TMenuItem; + MenuItem2: TMenuItem; + MenuItem3: TMenuItem; + MenuItem4: TMenuItem; + MenuItem51: TMenuItem; + MenuItem90: TMenuItem; + MenuItem91: TMenuItem; + MenuItem92: TMenuItem; + MenuItem93: TMenuItem; + MenuItem99: TMenuItem; + MnuHelp: TMenuItem; + MnuFileNew: TMenuItem; + MnuFileExit: TMenuItem; + MenuItem10: TMenuItem; + MenuItem100: TMenuItem; + MenuItem101: TMenuItem; + MenuItem107: TMenuItem; + MenuItem108: TMenuItem; + MenuItem109: TMenuItem; + MenuItem110: TMenuItem; + MenuItem111: TMenuItem; + MenuItem112: TMenuItem; + MenuItem113: TMenuItem; + MenuItem114: TMenuItem; + MenuItem115: TMenuItem; + MenuItem116: TMenuItem; + MenuItem117: TMenuItem; + MenuItem118: TMenuItem; + MenuItem119: TMenuItem; + MenuItem120: TMenuItem; + MenuItem121: TMenuItem; + MenuItem122: TMenuItem; + MenuItem123: TMenuItem; + MenuItem124: TMenuItem; + MenuItem125: TMenuItem; + MenuItem126: TMenuItem; + MenuItem127: TMenuItem; + MenuItem128: TMenuItem; + MenuItem129: TMenuItem; + MenuItem130: TMenuItem; + MenuItem132: TMenuItem; + MenuItem133: TMenuItem; + MenuItem134: TMenuItem; + MenuItem135: TMenuItem; + MenuItem141: TMenuItem; + MenuItem142: TMenuItem; + MenuItem143: TMenuItem; + MenuItem144: TMenuItem; + MenuItem145: TMenuItem; + MenuItem146: TMenuItem; + MenuItem148: TMenuItem; + MenuItem149: TMenuItem; + MenuItem150: TMenuItem; + MenuItem151: TMenuItem; + MenuItem152: TMenuItem; + MenuItem153: TMenuItem; + MenuItem154: TMenuItem; + MenuItem155: TMenuItem; + MenuItem156: TMenuItem; + MenuItem157: TMenuItem; + MenuItem50: TMenuItem; + MnuFileReopen: TMenuItem; + MnuZoom: TMenuItem; + MenuItem147: TMenuItem; + MnuSettings: TMenuItem; + MenuItem11: TMenuItem; + MenuItem12: TMenuItem; + MenuItem13: TMenuItem; + MenuItem14: TMenuItem; + MenuItem15: TMenuItem; + MenuItem16: TMenuItem; + MenuItem17: TMenuItem; + MenuItem18: TMenuItem; + MenuItem19: TMenuItem; + MenuItem20: TMenuItem; + MenuItem21: TMenuItem; + MenuItem22: TMenuItem; + MenuItem23: TMenuItem; + MenuItem24: TMenuItem; + MenuItem25: TMenuItem; + MenuItem26: TMenuItem; + MenuItem27: TMenuItem; + MenuItem28: TMenuItem; + MenuItem29: TMenuItem; + MenuItem30: TMenuItem; + MenuItem31: TMenuItem; + MenuItem32: TMenuItem; + MenuItem33: TMenuItem; + MenuItem34: TMenuItem; + MenuItem35: TMenuItem; + MenuItem36: TMenuItem; + MenuItem37: TMenuItem; + MenuItem38: TMenuItem; + MenuItem39: TMenuItem; + MenuItem40: TMenuItem; + MenuItem41: TMenuItem; + MenuItem42: TMenuItem; + MenuItem43: TMenuItem; + MenuItem44: TMenuItem; + MenuItem45: TMenuItem; + MenuItem46: TMenuItem; + MenuItem47: TMenuItem; + MenuItem48: TMenuItem; + MenuItem49: TMenuItem; + MenuItem5: TMenuItem; + MnuFileOpen: TMenuItem; + MnuFileSaveAs: TMenuItem; + MenuItem52: TMenuItem; + MenuItem53: TMenuItem; + MenuItem54: TMenuItem; + MenuItem55: TMenuItem; + MenuItem56: TMenuItem; + MenuItem57: TMenuItem; + MenuItem58: TMenuItem; + MenuItem59: TMenuItem; + MenuItem60: TMenuItem; + MenuItem61: TMenuItem; + MenuItem62: TMenuItem; + MenuItem63: TMenuItem; + MenuItem64: TMenuItem; + MenuItem65: TMenuItem; + MenuItem66: TMenuItem; + MenuItem67: TMenuItem; + MenuItem68: TMenuItem; + MenuItem69: TMenuItem; + MenuItem70: TMenuItem; + MenuItem71: TMenuItem; + MenuItem72: TMenuItem; + MenuItem73: TMenuItem; + MenuItem74: TMenuItem; + MenuItem75: TMenuItem; + MenuItem76: TMenuItem; + MenuItem77: TMenuItem; + MenuItem78: TMenuItem; + MenuItem79: TMenuItem; + MenuItem80: TMenuItem; + MenuItem81: TMenuItem; + MenuItem82: TMenuItem; + MenuItem83: TMenuItem; + MenuItem84: TMenuItem; + MenuItem85: TMenuItem; + MenuItem86: TMenuItem; + MenuItem87: TMenuItem; + MenuItem88: TMenuItem; + MenuItem89: TMenuItem; + MenuItem9: TMenuItem; + MenuItem95: TMenuItem; + MenuItem96: TMenuItem; + MenuItem97: TMenuItem; + MenuItem98: TMenuItem; + MenuItem94: TMenuItem; + MnuAddWorksheet: TMenuItem; + MnuView: TMenuItem; + MenuItem6: TMenuItem; + MenuItem7: TMenuItem; + MenuItem8: TMenuItem; + MnuFormat: TMenuItem; + MnuFile: TMenuItem; + MnuEdit: TMenuItem; + OpenDialog: TOpenDialog; + OpenDialog1: TOpenDialog; + CellEdit: TsCellEdit; + CellIndicator: TsCellIndicator; + AcFontBold: TsFontStyleAction; + AcFontItalic: TsFontStyleAction; + AcVertAlignTop: TsVertAlignmentAction; + AcVertAlignCenter: TsVertAlignmentAction; + AcVertAlignBottom: TsVertAlignmentAction; + AcHorAlignLeft: TsHorAlignmentAction; + AcHorAlignCenter: TsHorAlignmentAction; + AcHorAlignRight: TsHorAlignmentAction; + AcTextRotHor: TsTextRotationAction; + AcTextRot90CW: TsTextRotationAction; + AcTextRot90CCW: TsTextRotationAction; + AcTextRotStacked: TsTextRotationAction; + AcWordWrap: TsWordwrapAction; + AcNumFormatFixed: TsNumberFormatAction; + AcNumFormatFixedTh: TsNumberFormatAction; + AcNumFormatPercentage: TsNumberFormatAction; + AcNumFormatCurrency: TsNumberFormatAction; + AcNumFormatCurrencyRed: TsNumberFormatAction; + Panel2: TPanel; + PuRecentFiles: TPopupMenu; + PuPaste: TPopupMenu; + PuBorders: TPopupMenu; + PuTimeFormat: TPopupMenu; + PuDateFormat: TPopupMenu; + PuCurrencyFormat: TPopupMenu; + PuNumFormat: TPopupMenu; + AcNumFormatGeneral: TsNumberFormatAction; + AcNumFormatExp: TsNumberFormatAction; + AcNumFormatDateTime: TsNumberFormatAction; + AcNumFormatLongDate: TsNumberFormatAction; + AcNumFormatShortDate: TsNumberFormatAction; + AcNumFormatLongTime: TsNumberFormatAction; + AcNumFormatShortTime: TsNumberFormatAction; + AcNumFormatLongTimeAM: TsNumberFormatAction; + AcNumFormatShortTimeAM: TsNumberFormatAction; + AcNumFormatTimeInterval: TsNumberFormatAction; + AcIncDecimals: TsDecimalsAction; + AcDecDecimals: TsDecimalsAction; + AcCellFontDialog: TsFontDialogAction; + AcBackgroundColorDialog: TsBackgroundColorDialogAction; + AcCellBorderTop: TsCellBorderAction; + AcCellBorderBottom: TsCellBorderAction; + AcCellBorderLeft: TsCellBorderAction; + AcCellBorderRight: TsCellBorderAction; + AcCellBorderInnerHor: TsCellBorderAction; + AcCellBorderInnerVert: TsCellBorderAction; + AcCellBorderAllHor: TsCellBorderAction; + AcCellBorderBottomThick: TsCellBorderAction; + AcCellBorderBottomDbl: TsCellBorderAction; + AcCellBorderAllOuter: TsCellBorderAction; + AcCellBorderNone: TsNoCellBordersAction; + AcCellBorderAllOuterThick: TsCellBorderAction; + AcCellBorderTopBottomThick: TsCellBorderAction; + AcCellBorderTopBottomDbl: TsCellBorderAction; + AcCellBorderAll: TsCellBorderAction; + AcCellBorderAllVert: TsCellBorderAction; + AcCopyFormat: TsCopyAction; + FontColorCombobox: TsCellCombobox; + BackgroundColorCombobox: TsCellCombobox; + FontnameCombo: TsCellCombobox; + FontsizeCombo: TsCellCombobox; + AcMergeCells: TsMergeAction; + AcCopyToClipboard: TsCopyAction; + AcCutToClipboard: TsCopyAction; + AcPasteAllFromClipboard: TsCopyAction; + AcPasteValueFromClipboard: TsCopyAction; + AcPasteFormatFromClipboard: TsCopyAction; + AcPasteFormulaFromClipboard: TsCopyAction; + AcCommentNew: TsCellCommentAction; + AcCommentEdit: TsCellCommentAction; + AcCommentDelete: TsCellCommentAction; + AcHyperlinkNew: TsCellHyperlinkAction; + AcHyperlinkEdit: TsCellHyperlinkAction; + AcHyperlinkDelete: TsCellHyperlinkAction; + AcNumFormatFraction2: TsNumberFormatAction; + AcNumFormatFraction1: TsNumberFormatAction; + AcNumFormatFraction3: TsNumberFormatAction; + AcNumFormatDayMonth: TsNumberFormatAction; + AcNumFormatMonthYear: TsNumberFormatAction; + AcNumFormatCustom: TsNumberFormatAction; + AcCellBorderDiagUp: TsCellBorderAction; + AcCellBorderDiagDown: TsCellBorderAction; + AcNumFormatText: TsNumberFormatAction; + Splitter2: TSplitter; + Splitter3: TSplitter; + AcZoom100: TsWorksheetZoomAction; + AcZoom90: TsWorksheetZoomAction; + AcZoom30: TsWorksheetZoomAction; + AcZoom50: TsWorksheetZoomAction; + AcZoom75: TsWorksheetZoomAction; + AcZoom150: TsWorksheetZoomAction; + AcZoom200: TsWorksheetZoomAction; + AcZoom300: TsWorksheetZoomAction; + AcZoom500: TsWorksheetZoomAction; + ToolBar2: TToolBar; + ToolBar3: TToolBar; + ToolButton1: TToolButton; + ToolButton11: TToolButton; + ToolButton12: TToolButton; + ToolButton13: TToolButton; + ToolButton14: TToolButton; + ToolButton15: TToolButton; + ToolButton16: TToolButton; + ToolButton17: TToolButton; + ToolButton18: TToolButton; + ToolButton19: TToolButton; + AcFontUnderline: TsFontStyleAction; + AcFontStrikeout: TsFontStyleAction; + InspectorSplitter: TSplitter; + Inspector: TsSpreadsheetInspector; + InspectorTabControl: TTabControl; + AcAddWorksheet: TsWorksheetAddAction; + AcDeleteWorksheet: TsWorksheetDeleteAction; + acRenameWorksheet: TsWorksheetRenameAction; + ToolBar1: TToolBar; + ToolButton10: TToolButton; + ToolButton2: TToolButton; + ToolButton20: TToolButton; + ToolButton21: TToolButton; + ToolButton22: TToolButton; + ToolButton23: TToolButton; + ToolButton24: TToolButton; + ToolButton25: TToolButton; + ToolButton26: TToolButton; + ToolButton27: TToolButton; + ToolButton28: TToolButton; + ToolButton29: TToolButton; + ToolButton3: TToolButton; + ToolButton30: TToolButton; + ToolButton31: TToolButton; + TbBorders: TToolButton; + ToolButton32: TToolButton; + ToolButton33: TToolButton; + ToolButton34: TToolButton; + ToolButton35: TToolButton; + ToolButton36: TToolButton; + ToolButton37: TToolButton; + ToolButton38: TToolButton; + ToolButton39: TToolButton; + TbCommentAdd: TToolButton; + ToolButton4: TToolButton; + ToolButton40: TToolButton; + ToolButton41: TToolButton; + ToolButton42: TToolButton; + ToolButton43: TToolButton; + ToolButton44: TToolButton; + ToolButton45: TToolButton; + ToolButton46: TToolButton; + ToolButton47: TToolButton; + ToolButton48: TToolButton; + ToolButton49: TToolButton; + ToolButton5: TToolButton; + TbCommentDelete: TToolButton; + TbCommentEdit: TToolButton; + ToolButton50: TToolButton; + ToolButton51: TToolButton; + ToolButton52: TToolButton; + ToolButton53: TToolButton; + ToolButton54: TToolButton; + ToolButton55: TToolButton; + ToolButton6: TToolButton; + ToolButton7: TToolButton; + ToolButton8: TToolButton; + tbFileOpen: TToolButton; + ToolButton9: TToolButton; + WorkbookSource: TsWorkbookSource; + WorkbookTabControl: TsWorkbookTabControl; + WorksheetGrid: TsWorksheetGrid; + procedure AcAboutExecute(Sender: TObject); + procedure AcAutoRowHeightsExecute(Sender: TObject); + procedure AcColAddExecute(Sender: TObject); + procedure AcColDeleteExecute(Sender: TObject); + procedure AcColWidthExecute(Sender: TObject); + procedure AcFileNewExecute(Sender: TObject); + procedure AcFileOpenAccept(Sender: TObject); + procedure AcFileSaveAsAccept(Sender: TObject); + procedure AcFileSaveAsBeforeExecute(Sender: TObject); + procedure AcFrozenColsExecute(Sender: TObject); + procedure AcFrozenColsUpdate(Sender: TObject); + procedure AcFrozenRowsExecute(Sender: TObject); + procedure AcFrozenRowsUpdate(Sender: TObject); + procedure AcNumFormatCustomGetNumberFormatString(Sender: TObject; + AWorkbook: TsWorkbook; var ANumFormatStr: String); + procedure AcRowAddExecute(Sender: TObject); + procedure AcRowDeleteExecute(Sender: TObject); + procedure AcRowHeightExecute(Sender: TObject); + procedure AcSortColAscExecute(Sender: TObject); + procedure AcSortExecute(Sender: TObject); + procedure ActionListUpdate(AAction: TBasicAction; var Handled: Boolean); + procedure AcWorksheetRTLExecute(Sender: TObject); + procedure AcWorksheetRTLUpdate(Sender: TObject); + procedure AcSearchExecute(Sender: TObject); + procedure AcSettingsCSVParamsExecute(Sender: TObject); + procedure AcSettingsCurrencyExecute(Sender: TObject); + procedure AcSettingsFormatSettingsExecute(Sender: TObject); + procedure AcShowGridLinesExecute(Sender: TObject); + procedure AcShowGridLinesUpdate(Sender: TObject); + procedure AcShowHeadersExecute(Sender: TObject); + procedure AcShowHeadersUpdate(Sender: TObject); + procedure AcViewInspectorExecute(Sender: TObject); + procedure EditCut1Execute(Sender: TObject); + procedure ColorComboboxAddColors(Sender: TObject); + procedure FormCloseQuery(Sender: TObject; var CanClose: boolean); + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure HyperlinkHandler(Sender: TObject; ACaption: String; + var AHyperlink: TsHyperlink); + procedure InspectorEnter(Sender: TObject); + procedure InspectorExit(Sender: TObject); + procedure InspectorTabControlChange(Sender: TObject); + procedure TSaveDialogTypeChange(Sender: TObject); + procedure WorksheetGridClickHyperlink(Sender: TObject; + const AHyperlink: TsHyperlink); + procedure WorksheetGridMouseWheel(Sender: TObject; Shift: TShiftState; + WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); + private + { private declarations } + FOpenFormats: TsSpreadFormatIDArray; + FSaveFormats: TsSpreadFormatIDArray; + FMRUMenuManager: TMRUMenuManager; + procedure LoadFile(const AFileName: String); + procedure MRUMenuManagerRecentFile(Sender: TObject; const AFileName: string); + procedure SearchClose(Sender: TObject; var CloseAction: TCloseAction); + procedure SearchFound(Sender: TObject; AFound: Boolean; + AWorksheet: TsWorksheet; ARow, ACol: Cardinal); + procedure UpdateCaption; + procedure UpdateInspectorColumns; + protected + procedure ReadFromIni; + procedure WriteToIni; + public + { public declarations } + procedure BeforeRun; + end; + +var + MainForm: TMainForm; + + +implementation + +{$R *.lfm} + +uses + LCLIntf, inifiles, uriparser, ValEdit, + fpsUtils, fpsCSV, + sCSVParamsForm, sCurrencyForm, sFormatSettingsForm, sSortParamsForm, + sHyperlinkForm, sNumFormatForm, sSearchForm, sColWidthForm, sRowHeightForm, + sAbout; + +var + SEARCH_DLG_POS: TPoint = (X: -1; Y: -1); + +function CreateIni: TCustomIniFile; +begin + Result := TMemIniFile.Create(GetAppConfigFile(false)); +end; + + +{ TMainForm } + +procedure TMainForm.AcAboutExecute(Sender: TObject); +var + F: TAboutForm; +begin + F := TAboutForm.Create(nil); + try + F.ShowModal; + finally + F.Free; + end; +end; + +procedure TMainForm.AcAutoRowHeightsExecute(Sender: TObject); +begin + Screen.Cursor := crHourglass; + try + WorksheetGrid.UpdateRowHeights(0, true); + finally + Screen.Cursor := crDefault; + end; +end; + +{ Adds a column before the active cell } +procedure TMainForm.AcColAddExecute(Sender: TObject); +begin + WorksheetGrid.InsertCol(WorksheetGrid.Col); + WorksheetGrid.Col := WorksheetGrid.Col + 1; +end; + +{ Deletes the column with the active cell } +procedure TMainForm.AcColDeleteExecute(Sender: TObject); +var + c: Integer; +begin + c := WorksheetGrid.Col; + WorksheetGrid.DeleteCol(c); + WorksheetGrid.Col := c; +end; + +procedure TMainForm.AcColWidthExecute(Sender: TObject); +var + F: TColWidthForm; + sc: Cardinal; + book: TsWorkbook; + sheet: TsWorksheet; +begin + book := WorkbookSource.Workbook; + sheet := WorkbookSource.Worksheet; + sc := WorksheetGrid.GetWorksheetCol(WorksheetGrid.Col); + F := TColWidthForm.Create(nil); + try + F.Caption := 'Width of column ' + GetColString(sc); + F.SetData(book, sheet.GetColWidth(sc, book.Units), sheet.GetColWidthType(sc)); + if F.ShowModal = mrOK then begin + sheet.WriteColWidth(sc, F.ColWidth, F.Units, F.ColWidthType); + WorksheetGrid.UpdateColWidth(WorksheetGrid.Col); + end; + finally + F.Free; + end; +end; + +procedure TMainForm.AcFileNewExecute(Sender: TObject); +begin + WorkbookSource.CreateNewWorkbook; + + //WorksheetGrid.NewWorkbook(26, 100); + + WorksheetGrid.BeginUpdate; + try + WorksheetGrid.Col := WorksheetGrid.FixedCols; + WorksheetGrid.Row := WorksheetGrid.FixedRows; + UpdateCaption; + //SetupBackgroundColorBox; + //WorksheetGridSelection(nil, WorksheetGrid.Col, WorksheetGrid.Row); + finally + WorksheetGrid.EndUpdate; + end; +end; + +{ Loads the spreadsheet file selected by the AcFileOpen action } +procedure TMainForm.AcFileOpenAccept(Sender: TObject); +begin + WorkbookSource.AutodetectFormat := false; + case AcFileOpen.Dialog.FilterIndex of + 1: WorkbookSource.AutoDetectFormat := true; // All spreadsheet files + 2: WorkbookSource.AutoDetectFormat := true; // All Excel files + else WorkbookSource.FileFormatID := FOpenFormats[AcFileOpen.Dialog.FilterIndex - 3]; + // -3 because FilterIndex is 1-based and there are 2 add'l items at the top. + end; + LoadFile(AcFileOpen.Dialog.FileName); +end; + +{ Saves the spreadsheet to the file selected by the AcFileSaveAs action } +procedure TMainForm.AcFileSaveAsAccept(Sender: TObject); +var + fmt: TsSpreadFormatID; + fmts: TsSpreadFormatIDArray; + ext: String; +begin + Screen.Cursor := crHourglass; + try + fmt := FSaveFormats[AcFileSaveAs.Dialog.FilterIndex - 1]; + ext := ExtractFileExt(ACFileSaveAs.Dialog.Filename); + WorkbookSource.SaveToSpreadsheetFile(UTF8ToAnsi(AcFileSaveAs.Dialog.FileName), fmt); + UpdateCaption; + finally + Screen.Cursor := crDefault; + end; +end; + +procedure TMainForm.AcFileSaveAsBeforeExecute(Sender: TObject); +var + i: Integer; +begin + if WorkbookSource.FileName = '' then + exit; + + AcFileSaveAs.Dialog.InitialDir := ExtractFileDir(WorkbookSource.FileName); + AcFileSaveAs.Dialog.FileName := ExtractFileName(WorkbookSource.FileName); + + // Pre-select the file format according to the input file + if WorkbookSource.Workbook.FileFormatID = sfidUnknown then + exit; + for i:=0 to High(FSaveformats) do + if FSaveFormats[i] = WorkbookSource.Workbook.FileFormatID then begin + AcFileSaveAs.Dialog.FilterIndex := i + 1; + break; + end; +end; + +procedure TMainForm.AcFrozenColsExecute(Sender: TObject); +begin + if AcFrozenCols.Checked then + WorksheetGrid.FrozenCols := WorksheetGrid.GetWorksheetCol(WorksheetGrid.Col) + else + WorksheetGrid.FrozenCols := 0; +end; + +procedure TMainForm.AcFrozenColsUpdate(Sender: TObject); +begin + AcFrozenCols.Checked := WorksheetGrid.FrozenCols > 0; +end; + +procedure TMainForm.AcFrozenRowsExecute(Sender: TObject); +begin + if AcFrozenRows.Checked then + WorksheetGrid.FrozenRows := WorksheetGrid.GetWorksheetRow(WorksheetGrid.Row) + else + WorksheetGrid.FrozenRows := 0; +end; + +procedure TMainForm.AcFrozenRowsUpdate(Sender: TObject); +begin + AcFrozenRows.Checked := WorksheetGrid.FrozenRows > 0; +end; + +procedure TMainForm.AcNumFormatCustomGetNumberFormatString(Sender: TObject; + AWorkbook: TsWorkbook; var ANumFormatStr: String); +var + F: TNumFormatForm; + sample: Double; +begin + Unused(AWorkbook); + F := TNumFormatForm.Create(nil); + try + F.Position := poMainFormCenter; + with WorkbookSource.Worksheet do + sample := ReadAsNumber(ActiveCellRow, ActiveCellCol); + F.SetData(ANumFormatStr, WorkbookSource.Workbook, sample); + if F.ShowModal = mrOK then + ANumFormatStr := F.NumFormatStr; + finally + F.Free; + end; +end; + +{ Adds a row before the active cell } +procedure TMainForm.AcRowAddExecute(Sender: TObject); +begin + WorksheetGrid.InsertRow(WorksheetGrid.Row); + WorksheetGrid.Row := WorksheetGrid.Row + 1; +end; + +{ Deletes the row with the active cell } +procedure TMainForm.AcRowDeleteExecute(Sender: TObject); +var + r: Integer; +begin + r := WorksheetGrid.Row; + WorksheetGrid.DeleteRow(r); + WorksheetGrid.Row := r; +end; + +procedure TMainForm.AcRowHeightExecute(Sender: TObject); +var + F: TRowHeightForm; + sr: Cardinal; + book: TsWorkbook; + sheet: TsWorksheet; +begin + book := WorkbookSource.Workbook; + sheet := WorkbookSource.Worksheet; + sr := WorksheetGrid.GetWorksheetRow(WorksheetGrid.Row); + F := TRowHeightForm.Create(nil); + try + F.Caption := Format('Height of row %d', [WorksheetGrid.Row]); + F.SetData(book, sheet.GetRowHeight(sr, book.Units), sheet.GetRowHeightType(sr)); + if F.ShowModal = mrOK then begin + sheet.WriteRowHeight(sr, F.RowHeight, F.Units, F.RowHeightType); + WorksheetGrid.UpdateRowHeight(WorksheetGrid.Row, F.RowHeightType = rhtAuto); + end; + finally + F.Free; + end; +end; + +procedure TMainForm.AcWorksheetRTLExecute(Sender: TObject); +begin + if AcWorksheetRTL.Checked then + begin + if WorksheetGrid.IsRightToLeft then + WorksheetGrid.Worksheet.BiDiMode := bdLTR else + WorksheetGrid.Worksheet.BiDiMode := bdRTL; + end else + WorksheetGrid.Worksheet.BiDiMode := bdDefault; +end; + +procedure TMainForm.AcWorksheetRTLUpdate(Sender: TObject); +begin + AcWorksheetRTL.Checked := WorksheetGrid.Worksheet.BiDiMode <> bdDefault; +end; + +procedure TMainForm.AcSearchExecute(Sender: TObject); +begin + if SearchForm = nil then + SearchForm := TSearchForm.Create(self) + else + if not SearchForm.Showing then + begin + SearchForm.Position := poDesigned; + SearchForm.Left := SEARCH_DLG_POS.X; + SearchForm.Top := SEARCH_DLG_POS.Y; + end else + SearchForm.BringToFront; + SearchForm.OnFound := @SearchFound; + SearchForm.OnClose := @SearchClose; + SearchForm.SearchParams := DefaultSearchParams; + SearchForm.ReplaceParams := DefaultReplaceParams; + SearchForm.Execute(WorkbookSource.Workbook); +end; + +procedure TMainForm.AcSettingsCSVParamsExecute(Sender: TObject); +var + F: TCSVParamsForm; +begin + F := TCSVParamsForm.Create(nil); + try + F.SetParams(fpscsv.CSVParams); + if F.ShowModal = mrOK then + F.GetParams(fpscsv.CSVParams); + finally + F.Free; + end; +end; + +procedure TMainForm.AcSettingsCurrencyExecute(Sender: TObject); +var + F: TCurrencyForm; +begin + F := TCurrencyForm.Create(nil); + try + F.ShowModal; + finally + F.Free; + end; +end; + +procedure TMainForm.AcSettingsFormatSettingsExecute(Sender: TObject); +var + F: TFormatSettingsForm; +begin + if WorksheetGrid.Workbook = nil then + exit; + + F := TFormatSettingsForm.Create(nil); + try + F.FormatSettings := WorksheetGrid.Workbook.FormatSettings; + if F.ShowModal = mrOK then + begin + WorksheetGrid.Workbook.FormatSettings := F.FormatSettings; + WorksheetGrid.Invalidate; + end; + finally + F.Free; + end; +end; + +procedure TMainForm.AcShowGridLinesExecute(Sender: TObject); +begin + WorksheetGrid.ShowGridLines := AcShowGridLines.Checked; +end; + +procedure TMainForm.AcShowGridLinesUpdate(Sender: TObject); +begin + AcShowGridLines.Checked := WorksheetGrid.ShowGridLines; +end; + +procedure TMainForm.AcShowHeadersExecute(Sender: TObject); +begin + WorksheetGrid.ShowHeaders := AcShowHeaders.Checked; +end; + +procedure TMainForm.AcShowHeadersUpdate(Sender: TObject); +begin + AcShowHeaders.Checked := WorksheetGrid.ShowHeaders; +end; + +procedure TMainForm.AcSortColAscExecute(Sender: TObject); +var + c: Cardinal; + sortParams: TsSortParams; +begin + c := WorksheetGrid.GetWorksheetCol(WorksheetGrid.Col); + sortParams := InitSortParams; + WorksheetGrid.BeginUpdate; + try + with WorkbookSource.Worksheet do + Sort(sortParams, 0, c, GetLastOccupiedRowIndex, c); + finally + WorksheetGrid.EndUpdate; + end; +end; + +procedure TMainForm.AcSortExecute(Sender: TObject); +var + F: TSortParamsForm; + r1,c1,r2,c2: Cardinal; +begin + F := TSortParamsForm.Create(nil); + try + F.WorksheetGrid := WorksheetGrid; + if F.ShowModal = mrOK then + begin + // Limits of the range to be sorted + with WorksheetGrid do begin + r1 := GetWorksheetRow(Selection.Top); + c1 := GetWorksheetCol(Selection.Left); + r2 := GetWorksheetRow(Selection.Bottom); + c2 := GetWorksheetCol(Selection.Right); + end; + // Execute sorting. Use Begin/EndUpdate to avoid unnecessary redraws. + WorksheetGrid.BeginUpdate; + try + WorksheetGrid.Worksheet.Sort(F.SortParams, r1, c1, r2, c2) + finally + WorksheetGrid.EndUpdate; + end; + end; + finally + F.Free; + end; +end; + +procedure TMainForm.ActionListUpdate(AAction: TBasicAction; var Handled: Boolean + ); +begin + if AAction = AcAutoRowHeights then + AcAutoRowHeights.Enabled := WorkbookSource.Worksheet <> nil; +end; + +{ Toggles the spreadsheet inspector on and off } +procedure TMainForm.AcViewInspectorExecute(Sender: TObject); +begin + InspectorTabControl.Visible := AcViewInspector.Checked; + InspectorSplitter.Visible := AcViewInspector.Checked; + InspectorSplitter.Left := 0; + // Make sure that the splitter is always at the left of the inspector tabcontrol + UpdateInspectorColumns; +end; + +procedure TMainForm.BeforeRun; +begin + ReadFromIni; +end; + +procedure TMainForm.ColorComboboxAddColors(Sender: TObject); +begin + with TsCellCombobox(Sender) do begin + // These are the Excel-8 palette colors, a bit rearranged and without the + // duplicates. + AddColor($000000, 'black'); + AddColor($333333, 'gray 80%'); + AddColor($808080, 'gray 50%'); + AddColor($969696, 'gray 40%'); + AddColor($C0C0C0, 'silver'); + AddColor($FFFFFF, 'white'); + AddColor($FF0000, 'red'); + AddColor($00FF00, 'green'); + AddColor($0000FF, 'blue'); + AddColor($FFFF00, 'yellow'); + AddColor($FF00FF, 'magenta'); + AddColor($00FFFF, 'cyan'); + + AddColor($800000, 'dark red'); + AddColor($008000, 'dark green'); + AddColor($000080, 'dark blue'); + AddColor($808000, 'olive'); + AddColor($800080, 'purple'); + AddColor($008080, 'teal'); + AddColor($9999FF, 'periwinkle'); + AddColor($993366, 'plum'); + AddColor($FFFFCC, 'ivory'); + AddColor($CCFFFF, 'light turquoise'); + AddColor($660066, 'dark purple'); + AddColor($FF8080, 'coral'); + AddColor($0066CC, 'ocean blue'); + AddColor($CCCCFF, 'ice blue'); + + AddColor($00CCFF, 'sky blue'); + AddColor($CCFFCC, 'light green'); + AddColor($FFFF99, 'light yellow'); + AddColor($99CCFF, 'pale blue'); + AddColor($FF99CC, 'rose'); + AddColor($CC99FF, 'lavander'); + AddColor($FFCC99, 'tan'); + + AddColor($3366FF, 'light blue'); + AddColor($33CCCC, 'aqua'); + AddColor($99CC00, 'lime'); + AddColor($FFCC00, 'gold'); + AddColor($FF9900, 'light orange'); + AddColor($FF6600, 'orange'); + AddColor($666699, 'blue gray'); + AddColor($003366, 'dark teal'); + AddColor($339966, 'sea green'); + AddColor($003300, 'very dark green'); + AddColor($333300, 'olive green'); + AddColor($993300, 'brown'); + AddColor($333399, 'indigo'); + end; +end; + +procedure TMainForm.EditCut1Execute(Sender: TObject); +begin + // +end; + +procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: boolean); +begin + if CanClose then + try + WriteToIni; + except + end; +end; + +procedure TMainForm.FormCreate(Sender: TObject); +var + priorityFormats: Array[0..8] of TsSpreadFormatID; +begin + FMRUMenuManager := TMRUMenuManager.Create(self); + with FMRUMenuManager do begin + Name := 'MRUMenuManager'; + IniFileName := GetAppConfigFile(false); + IniSection := 'RecentFiles'; + MaxRecent := 16; + MenuCaptionMask := '&%x - %s'; // & --> create hotkey + MenuItem := MnuFileReopen; + PopupMenu := PuRecentFiles; + OnRecentFile := @MRUMenuManagerRecentFile; + end; + + priorityFormats[0] := ord(sfOOXML); + priorityFormats[1] := ord(sfExcel8); + priorityFormats[2] := ord(sfExcel5); + priorityFormats[3] := ord(sfExcel2); + priorityFormats[4] := ord(sfExcelXML); + priorityFormats[5] := ord(sfOpenDocument); + priorityFormats[6] := ord(sfCSV); + priorityFormats[7] := sfidSYLK; + priorityFormats[8] := ord(sfHTML); + + AcFileOpen.Dialog.Filter := GetFileFormatFilter('|', ';', faRead, priorityFormats, true, true); + FOpenFormats := GetSpreadFormats(faRead, priorityFormats); + + AcFileSaveAs.Dialog.Filter := GetFileFormatFilter('|', ';', faWrite, priorityFormats); + FSaveFormats := GetSpreadFormats(faWrite, priorityFormats); + + {$IFDEF WINDOWS} + if Win32MajorVersion >= 10 then begin + // avoid the ugly themed grid of Win10... + WorksheetGrid.TitleStyle := tsLazarus; + Inspector.TitleStyle := tsLazarus; + end; + {$ENDIF} +end; + +procedure TMainForm.FormShow(Sender: TObject); +begin + UpdateInspectorColumns; +end; + +{ Event handler for hyperlinks: it only has to provide the hyperlink data + which are applied to the active cell by the TsCellHyperlinkAction. + Is called by the "new hyperlink" and "edit hyperlink" actions. + Here we open the HyperlinkForm which is similar to the one used by + Open/LibreOffice. + + Caption .... Caption of the form in which the hyperlink can be specified + Hyperlink .. Data record (target, tooltip) for/from the the hyperlink form. } +procedure TMainForm.HyperlinkHandler(Sender: TObject; ACaption: String; + var AHyperlink: TsHyperlink); +begin + if HyperlinkForm = nil then + HyperlinkForm := THyperlinkForm.Create(self); + HyperlinkForm.Caption := ACaption; + HyperlinkForm.SetHyperlink(WorkbookSource.Worksheet, AHyperlink); + if HyperlinkForm.ShowModal = mrOK then + HyperlinkForm.GetHyperlink(AHyperlink); +end; + +procedure TMainForm.InspectorEnter(Sender: TObject); +begin + Inspector.Options := Inspector.Options + [goDrawFocusSelected]; +end; + +procedure TMainForm.InspectorExit(Sender: TObject); +begin + Inspector.Options := Inspector.Options - [goDrawFocusSelected]; +end; + +{ Event handler to synchronize the mode of the spreadsheet inspector with the + selected tab of the TabControl } +procedure TMainForm.InspectorTabControlChange(Sender: TObject); +begin + Inspector.Mode := TsInspectorMode(InspectorTabControl.TabIndex); + UpdateInspectorColumns; +end; + +procedure TMainForm.LoadFile(const AFileName: String); +var + crs: TCursor; +begin + crs := Screen.Cursor; + Screen.Cursor := crHourglass; + try + WorkbookSource.FileName := UTF8ToAnsi(AFileName); // this loads the file + FMRUMenuManager.AddToRecent(AFileName); + UpdateCaption; + finally + Screen.Cursor := crs; + end; +end; + +procedure TMainForm.MRUMenuManagerRecentFile(Sender: TObject; + const AFileName: string); +begin + WorkbookSource.AutoDetectFormat := true; + LoadFile(AFileName); +end; + +procedure TMainForm.ReadFromIni; +var + ini: TCustomIniFile; + s: String; + b: Boolean; + L,T,W,H: Integer; + Rect: TRect; +begin + ini := CreateIni; + try + L := ini.ReadInteger('MainForm', 'Left', Left); + T := ini.ReadInteger('MainForm', 'Top', Top); + W := ini.ReadInteger('MainForm', 'Width', Width); + H := ini.ReadInteger('MainForm', 'Height', Height); + Rect := Screen.DesktopRect; + if W > Rect.Right - Rect.Left then W := Rect.Right - Rect.Left; + if H > Rect.Bottom - Rect.Top then H := Rect.Bottom - Rect.Top; + if L + W > Rect.Right then L := Rect.Right - W; + if L < Rect.Left then L := Rect.Left; + if T + H > Rect.Bottom then T := Rect.Bottom - H; + if T < Rect.Top then T := Rect.Top; + SetBounds(L, T, W, H); + if ini.ReadBool('MainForm', 'Maximized', WindowState = wsMaximized) then + WindowState := wsMaximized else + WindowState := wsNormal; + + InspectortabControl.Width := ini.ReadInteger('Inspector', + 'Width', InspectorTabControl.Width); + s := ini.ReadString('Inspector', 'Page', ''); + if s <> '' then + InspectorTabControl.PageIndex := InspectorTabControl.Pages.IndexOf(s);; + b := ini.ReadBool('Inspector', 'Visible', false); + AcViewInspector.Checked := b; + AcviewInspectorExecute(nil); + finally + ini.Free; + end; +end; + +procedure TMainForm.SearchClose(Sender: TObject; var CloseAction: TCloseAction); +begin + Unused(CloseAction); + DefaultSearchParams := TSearchForm(Sender).SearchParams; + DefaultReplaceParams := TSearchForm(Sender).ReplaceParams; + SEARCH_DLG_POS.X := SearchForm.Left; + SEARCH_DLG_POS.Y := SearchForm.Top; +end; + +procedure TMainForm.SearchFound(Sender: TObject; AFound: Boolean; + AWorksheet: TsWorksheet; ARow, ACol: Cardinal); +begin + Unused(AWorksheet, ARow, ACol); + + if AFound then + begin + // + end + else + begin + DefaultSearchParams := TSearchForm(Sender).SearchParams; + MessageDlg( + Format('The search text "%s" could not be found.', [DefaultSearchParams.SearchText]), + mtInformation, + [mbOK], 0 + ); + end; +end; + +procedure TMainForm.TSaveDialogTypeChange(Sender: TObject); +var + ext: String; +begin + ext := GetSpreadFormatExt(FSaveFormats[AcFileSaveAs.Dialog.FilterIndex - 1]); + AcFileSaveAs.Dialog.FileName := ChangeFileExt(AcFileSaveAs.Dialog.FileName, ext); +end; + +procedure TMainForm.UpdateCaption; +begin + if (WorkbookSource = nil) or (WorkbookSource.FileName = '') then + Caption := 'spready' + else + Caption := Format('spready - "%s" [%s]', [ + AnsiToUTF8(WorkbookSource.Filename), + GetSpreadTechnicalName(WorkbookSource.Workbook.FileFormatID) + ]); +end; + +procedure TMainForm.UpdateInspectorColumns; +begin + Inspector.DisplayOptions := Inspector.DisplayOptions + [doAutoColResize]; + Inspector.DisplayOptions := Inspector.DisplayOptions - [doAutoColResize]; +end; + +procedure TMainForm.WriteToIni; +var + ini: TCustomIniFile; +begin + ini := CreateIni; + try + ini.WriteBool('MainForm', 'Maximized', WindowState = wsMaximized); + if WindowState = wsNormal then begin + ini.WriteInteger('MainForm', 'Left', Left); + ini.WriteInteger('MainForm', 'Top', Top); + ini.WriteInteger('MainForm', 'Width', Width); + ini.WriteInteger('MainForm', 'Height', Height); + end; + + ini.WriteInteger('Inspector', 'Width', InspectorTabControl.Width); + ini.WriteString('Inspector', 'Page', InspectorTabControl.Tabs[InspectorTabControl.TabIndex]); + ini.WriteBool('Inspector', 'Visible', InspectorTabControl.Visible); + finally + ini.Free; + end; +end; + +{ Event handler if an external hyperlink in a cell is activated. Usually the + linked documents/web sites etc. are opened. } +procedure TMainForm.WorksheetGridClickHyperlink(Sender: TObject; + const AHyperlink: TsHyperlink); +var + u: TUri; +begin + u := ParseURI(AHyperlink.Target); + case Lowercase(u.Protocol) of + 'http', 'https', 'ftp', 'mailto', 'file': + OpenUrl(AHyperlink.Target); + else + ShowMessage('Hyperlink ' + AHyperlink.Target + ' clicked'); + end; +end; + +procedure TMainForm.WorksheetGridMouseWheel(Sender: TObject; + Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; + var Handled: Boolean); +const + GROWTH_FACTOR = 1.05; +begin + if ([ssCtrl, ssShift] * Shift = [ssCtrl, ssShift]) then begin + if WheelDelta > 0 then + WorksheetGrid.ZoomFactor := GROWTH_FACTOR* WorksheetGrid.ZoomFactor + else + WorksheetGrid.ZoomFactor := WorksheetGrid.ZoomFactor / GROWTH_FACTOR; + Handled := true; + end; +end; + +end. + diff --git a/applications/spready/snumformatform.lfm b/applications/spready/snumformatform.lfm new file mode 100644 index 000000000..f9fad4d69 --- /dev/null +++ b/applications/spready/snumformatform.lfm @@ -0,0 +1,387 @@ +object NumFormatForm: TNumFormatForm + Left = 336 + Height = 394 + Top = 173 + Width = 559 + BorderStyle = bsDialog + Caption = 'Number format' + ClientHeight = 394 + ClientWidth = 559 + ShowHint = True + LCLVersion = '1.7' + object ButtonPanel1: TButtonPanel + Left = 6 + Height = 34 + Top = 354 + Width = 547 + OKButton.Name = 'OKButton' + OKButton.Hint = 'Accept changes and close' + OKButton.DefaultCaption = True + HelpButton.Name = 'HelpButton' + HelpButton.DefaultCaption = True + CloseButton.Name = 'CloseButton' + CloseButton.DefaultCaption = True + CancelButton.Name = 'CancelButton' + CancelButton.Hint = 'Discard changes and close' + CancelButton.DefaultCaption = True + TabOrder = 2 + ShowButtons = [pbOK, pbCancel] + end + object Panel1: TPanel + Left = 0 + Height = 297 + Top = 0 + Width = 122 + Align = alLeft + BevelOuter = bvNone + ClientHeight = 297 + ClientWidth = 122 + TabOrder = 0 + object Label1: TLabel + Left = 6 + Height = 15 + Top = 6 + Width = 112 + Align = alTop + BorderSpacing.Left = 2 + BorderSpacing.Top = 2 + BorderSpacing.Bottom = 2 + BorderSpacing.Around = 4 + Caption = 'Category' + Font.Style = [fsBold] + ParentColor = False + ParentFont = False + end + object LbCategory: TListBox + Left = 6 + Height = 270 + Top = 27 + Width = 116 + Align = alClient + BorderSpacing.Left = 6 + Items.Strings = ( + 'Number' + 'Percent' + 'Scientific' + 'Fraction' + 'Currency' + 'Date' + 'Time' + 'Text' + ) + ItemHeight = 15 + OnClick = LbCategoryClick + TabOrder = 0 + end + end + object Panel2: TPanel + Left = 122 + Height = 297 + Top = 0 + Width = 230 + Align = alLeft + BevelOuter = bvNone + ClientHeight = 297 + ClientWidth = 230 + TabOrder = 1 + object Label2: TLabel + Left = 6 + Height = 15 + Top = 6 + Width = 220 + Align = alTop + BorderSpacing.Left = 2 + BorderSpacing.Top = 2 + BorderSpacing.Bottom = 2 + BorderSpacing.Around = 4 + Caption = 'Format' + Font.Style = [fsBold] + ParentColor = False + ParentFont = False + end + object LbFormat: TListBox + Left = 6 + Height = 225 + Top = 27 + Width = 224 + Align = alClient + BorderSpacing.Left = 6 + ItemHeight = 0 + OnClick = LbFormatClick + OnDrawItem = LbFormatDrawItem + Style = lbOwnerDrawFixed + TabOrder = 0 + end + object CurrSymbolPanel: TPanel + Left = 6 + Height = 41 + Top = 256 + Width = 224 + Align = alBottom + BorderSpacing.Left = 6 + BorderSpacing.Top = 4 + BevelOuter = bvNone + ClientHeight = 41 + ClientWidth = 224 + TabOrder = 1 + Visible = False + object Label5: TLabel + Left = 0 + Height = 15 + Top = 0 + Width = 224 + Align = alTop + BorderSpacing.Bottom = 2 + Caption = 'Currency string' + Font.Style = [fsBold] + ParentColor = False + ParentFont = False + end + object CbCurrSymbol: TComboBox + Left = 0 + Height = 23 + Hint = 'List of registered currency symbols' + Top = 16 + Width = 200 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + OnSelect = CbCurrSymbolSelect + Style = csDropDownList + TabOrder = 0 + end + object BtnAddCurrSymbol: TSpeedButton + Left = 201 + Height = 23 + Hint = 'Add new currency symbol' + Top = 16 + Width = 23 + Anchors = [akTop, akRight] + Caption = '...' + OnClick = BtnAddCurrSymbolClick + end + end + end + object DetailsPanel: TPanel + Left = 352 + Height = 297 + Top = 0 + Width = 207 + Align = alClient + BevelOuter = bvNone + ClientHeight = 297 + ClientWidth = 207 + TabOrder = 3 + object GbOptions: TGroupBox + Left = 8 + Height = 121 + Top = 7 + Width = 187 + Anchors = [akTop, akLeft, akRight] + Caption = 'Options' + ClientHeight = 101 + ClientWidth = 183 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 0 + object Label3: TLabel + Left = 15 + Height = 15 + Top = 11 + Width = 79 + Caption = 'Decimal places' + ParentColor = False + ParentFont = False + end + object EdDecimals: TSpinEdit + Left = 121 + Height = 23 + Top = 7 + Width = 50 + Anchors = [akTop, akRight] + MaxValue = 16 + OnChange = EdDecimalsChange + ParentFont = False + TabOrder = 0 + end + object CbThousandSep: TCheckBox + Left = 15 + Height = 19 + Top = 40 + Width = 125 + Caption = 'Thousand separator' + OnClick = CbThousandSepClick + ParentFont = False + TabOrder = 1 + end + object CbNegRed: TCheckBox + Left = 15 + Height = 19 + Top = 67 + Width = 100 + Caption = 'Negative in red' + OnClick = CbNegRedClick + ParentFont = False + TabOrder = 2 + end + end + object GroupBox3: TGroupBox + Left = 8 + Height = 62 + Top = 136 + Width = 187 + Anchors = [akTop, akLeft, akRight] + Caption = 'Sample' + ClientHeight = 42 + ClientWidth = 183 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 1 + object Shape1: TShape + Left = 8 + Height = 34 + Top = 0 + Width = 167 + Align = alClient + BorderSpacing.Left = 8 + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 8 + end + object Sample: TLabel + Left = 9 + Height = 32 + Top = 1 + Width = 165 + Align = alClient + Alignment = taCenter + AutoSize = False + BorderSpacing.Left = 8 + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 8 + BorderSpacing.Around = 1 + Caption = 'Sample' + Color = clWhite + Layout = tlCenter + ParentColor = False + ParentFont = False + Transparent = False + end + end + end + object GbFormatString: TGroupBox + Left = 6 + Height = 47 + Top = 301 + Width = 547 + Align = alBottom + BorderSpacing.Left = 6 + BorderSpacing.Top = 4 + BorderSpacing.Right = 6 + Caption = 'Format string' + ClientHeight = 27 + ClientWidth = 543 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 4 + object EdNumFormatStr: TEdit + Left = 8 + Height = 23 + Hint = 'Number format string' + Top = 0 + Width = 483 + Anchors = [akTop, akLeft, akRight] + OnChange = EdNumFormatStrChange + ParentFont = False + TabOrder = 0 + end + object BtnAddFormat: TSpeedButton + Left = 493 + Height = 23 + Hint = 'Add this format string to list' + Top = 0 + Width = 23 + Anchors = [akTop, akRight] + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0041924E233D8F497D3A8C44DB368940F332873CF32F84 + 37DB2C81337D287F3023FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0049995853459653E6419950FF7DC28FFF96D0A6FF96CFA6FF78BE + 89FF368D42FF2C8134E6297F3053FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00519F61534D9C5DF464B478FFA8DBB5FF87CC98FF66BC7DFF64BA7CFF86CB + 98FFA5D9B4FF58AA6BFF2C8134F4297F3053FFFFFF00FFFFFF00FFFFFF0059A6 + 6B2256A366E56AB97DFFA8DBB2FF60BC77FF5CBA73FF59B870FF59B56FFF58B5 + 6FFF5BB774FFA5D9B3FF5AAA6CFF2C8234E5297F3022FFFFFF00FFFFFF005DA9 + 707E53AB68FFAADDB4FF64C179FF5FBE71FF60BC77FFFFFFFFFFFFFFFFFF59B8 + 70FF58B56EFF5CB774FFA6DAB4FF388F43FF2C82347EFFFFFF00FFFFFF0061AC + 75DB8ACC98FF89D396FF6BC67AFF63C170FF55AB65FFFFFFFFFFFFFFFFFF59B8 + 70FF59B870FF5BB972FF85CC97FF7BBE8DFF308539DBFFFFFF00FFFFFF0065AF + 7AF6A9DDB3FF7DCF8AFF75CC81FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF67BE7DFF9CD4ABFF34883DF6FFFFFF00FFFFFF0069B2 + 7EF6B6E2BEFF8BD597FF7AC986FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF69C17EFF9DD4AAFF388B42F6FFFFFF00FFFFFF006DB5 + 83DBACDDB6FFA6DFAFFF81CB8CFF7CC986FF6EBD79FFFFFFFFFFFFFFFFFF5BAC + 6AFF60BC77FF5CBA73FF8BD199FF80C592FF3C8E47DBFFFFFF00FFFFFF0070B8 + 877E85C797FFD2EED7FF95D9A0FF8AD394FF7FC889FFFFFFFFFFFFFFFFFF79CD + 85FF6BC37CFF6FC77EFFACDFB5FF459E57FF40914C7EFFFFFF00FFFFFF0073BA + 8A2270B887E5AADAB7FFD8F1DCFF92D89DFF88CD93FF84CC8EFF8BD496FF8AD4 + 95FF83D28EFFAFE0B7FF6BB97DFF489856E544945122FFFFFF00FFFFFF00FFFF + FF0073BB8B5370B887F4AFDCBBFFDCF2E0FFB6E4BDFF9BDBA5FF96D9A0FFA5DF + AFFFC0E8C5FF79C28AFF509E5FF44C9B5B53FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0073BB8B5371B887E694CEA4FFC3E6CBFFCFEBD4FFC9E9CEFFAFDD + B8FF6DB97FFF58A569E654A16553FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0074BB8B2371B9887D6EB684DB6AB380F367B17CF363AE + 77DB60AB737D5CA86E23FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = BtnAddFormatClick + end + object BtnDeleteFormat: TSpeedButton + Left = 516 + Height = 23 + Hint = 'Remove this format string from list' + Top = 0 + Width = 23 + Anchors = [akTop, akRight] + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF003F54C3233A50C27D3853BEDB3551BDF3304BBCF32E4E + B8DB2B4CB77D2748B523FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF004658C8534255C6E63C52CCFF757AE8FF8F92EEFF8F92EEFF7178 + E4FF334DC1FF2B4AB7E6294BB553FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF004D5ACD534959CBF45C65E0FFA1A6F5FF7E86EFFF5B63E9FF595DE7FF7D84 + EEFF9EA0F4FF515DD7FF2B4AB7F4294BB553FFFFFF00FFFFFF00FFFFFF00545F + D2225361CFE5616BE3FFA1ACF5FF545FECFF505CEAFF4D59E9FF4E59E6FF4C56 + E6FF5056E6FF9EA2F4FF5460D6FF2A4AB8E5294BB522FFFFFF00FFFFFF005860 + D47E4B56DBFFA2ABF6FF5664F0FF5266EEFF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4C58E6FF525AE6FF9FA3F5FF3450C4FF2A4AB87EFFFFFF00FFFFFF005C62 + D7DB818CEEFF7E91F7FF5D73F3FF4D59E9FF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4D59E9FF4F5BE9FF7B83F0FF757BE2FF2E4BBADBFFFFFF00FFFFFF005F63 + DAF6A1ABF7FF7086F8FF6882F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5C66EAFF969CF1FF3250BCF6FFFFFF00FFFFFF006469 + DBF6AFB9F9FF7F93FAFF7085F0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5E6AEEFF969DF1FF364FBEF6FFFFFF00FFFFFF00676A + DEDBA5AFF5FF9DABFAFF778CF0FF545FECFF545FECFF545FECFF545FECFF545F + ECFF545FECFF6377F2FF818EF4FF787FE9FF3A53C0DBFFFFFF00FFFFFF006A69 + E07E7D83EAFFCDD4FCFF8B9DFAFF7E93F7FF758AEEFF6C84F6FF6C84F6FF6C84 + F6FF6C84F6FF6379F3FFA4AFF8FF3E4FD0FF3E54C27EFFFFFF00FFFFFF006C6C + E1226A69E0E5A3A7F3FFD4DBFDFF879AFAFF7F91F0FF7A8EF1FF7F94F8FF7E92 + F9FF768CF8FFA8B6F8FF636EE3FF4557C7E54156C522FFFFFF00FFFFFF00FFFF + FF006D6CE3536A69E0F4AAADF2FFD8DCFDFFAEBAFAFF91A3FAFF8B9DFAFF9CA9 + FBFFBAC7FCFF707BE9FF4C5BCCF44858CA53FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF006D6CE3536A6ADFE68E93EDFFBEC3F8FFCCD3F9FFC4CBF9FFAAB4 + F4FF6670E2FF535ED1E6505DCE53FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF006D6DE2236B6AE17D686ADDDB6364DCF36164DAF35D63 + D9DB5B63D67D5862D423FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = BtnDeleteFormatClick + end + end +end diff --git a/applications/spready/snumformatform.pas b/applications/spready/snumformatform.pas new file mode 100644 index 000000000..4652c0389 --- /dev/null +++ b/applications/spready/snumformatform.pas @@ -0,0 +1,829 @@ +unit sNumFormatForm; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ButtonPanel, + ExtCtrls, StdCtrls, Spin, Buttons, types, inifiles, + fpsTypes, fpsNumFormat, fpSpreadsheet; + +type + TsNumFormatCategory = (nfcNumber, nfcPercent, nfcScientific, nfcFraction, + nfcCurrency, nfcDate, nfcTime, nfcText); + + { TNumFormatForm } + + TNumFormatForm = class(TForm) + ButtonPanel1: TButtonPanel; + CbThousandSep: TCheckBox; + CbNegRed: TCheckBox; + CbCurrSymbol: TComboBox; + EdNumFormatStr: TEdit; + GbOptions: TGroupBox; + GbFormatString: TGroupBox; + GroupBox3: TGroupBox; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + DetailsPanel: TPanel; + Sample: TLabel; + Label5: TLabel; + LbCategory: TListBox; + LbFormat: TListBox; + Panel1: TPanel; + Panel2: TPanel; + EdDecimals: TSpinEdit; + CurrSymbolPanel: TPanel; + BtnAddCurrSymbol: TSpeedButton; + Shape1: TShape; + BtnAddFormat: TSpeedButton; + BtnDeleteFormat: TSpeedButton; + procedure BtnAddCurrSymbolClick(Sender: TObject); + procedure BtnAddFormatClick(Sender: TObject); + procedure BtnDeleteFormatClick(Sender: TObject); + procedure CbCurrSymbolSelect(Sender: TObject); + procedure CbNegRedClick(Sender: TObject); + procedure CbThousandSepClick(Sender: TObject); + procedure EdDecimalsChange(Sender: TObject); + procedure EdNumFormatStrChange(Sender: TObject); + procedure LbCategoryClick(Sender: TObject); + procedure LbFormatClick(Sender: TObject); + procedure LbFormatDrawItem(Control: TWinControl; Index: Integer; + ARect: TRect; State: TOwnerDrawState); + private + { private declarations } + FWorkbook: TsWorkbook; + FSampleValue: Double; + FSampleText: String; + FGenerator: array[TsNumFormatCategory] of Double; + FNumFormatStrOfList: String; + FLockCount: Integer; + function GetNumFormatStr: String; + procedure SetNumFormatStr(const AValue: String); + protected + function FindNumFormat(ACategory: TsNumFormatCategory; + ANumFormatStr: String): Integer; + function FormatStrOfListIndex(AIndex: Integer): String; + procedure ReplaceCurrSymbol; + procedure ReplaceDecs; + procedure SelectCategory(ACategory: TsNumFormatCategory); + procedure SelectFormat(AIndex: Integer); + procedure UpdateControls(ANumFormatParams: TsNumFormatParams); + procedure UpdateSample(ANumFormatParams: TsNumFormatParams); + public + { public declarations } + constructor Create(AOwner: TComponent); override; + procedure SetData(ANumFormatStr: String; AWorkbook: TsWorkbook; + ASample: variant); + property NumFormatStr: String read GetNumFormatStr; + end; + +var + NumFormatForm: TNumFormatForm; + +procedure ReadNumFormatsFromIni(const AIniFile: TCustomIniFile); +procedure WriteNumFormatsToIni(const AIniFile: TCustomIniFile); + +implementation + +{$R *.lfm} + +uses + LCLType, Math, DateUtils, TypInfo, variants, + fpsUtils, fpsNumFormatParser, fpsCurrency, + sCurrencyForm; + +const + BUILTIN_OFFSET = 1; + USER_OFFSET = 1000; + +var + NumFormats: TStringList = nil; + +procedure AddToList(ACategory: TsNumFormatCategory; AFormatStr: String; + AOffset: Integer = BUILTIN_OFFSET); +begin + if NumFormats.IndexOf(AFormatStr) = -1 then + NumFormats.AddObject(AFormatStr, TObject(PtrInt(AOffset + ord(ACategory)))); +end; + +procedure InitNumFormats(AFormatSettings: TFormatSettings); +var + copiedFormats: TStringList; + nfs: String; + data: PtrInt; + i: Integer; + fs: TFormatSettings absolute AFormatSettings; +begin + copiedFormats := nil; + + // Store user-defined formats already added to NumFormats list + if NumFormats <> nil then + begin + copiedFormats := TStringList.Create; + for i:=0 to NumFormats.Count-1 do + begin + nfs := NumFormats.Strings[i]; + data := PtrInt(NumFormats.Objects[i]); + if data >= USER_OFFSET then + copiedFormats.AddObject(nfs, TObject(data)); + end; + NumFormats.Free; + end; + + NumFormats := TStringList.Create; + + // Add built-in formats + AddToList(nfcNumber, 'General'); + AddToList(nfcNumber, '0'); + AddToList(nfcNumber, '0.0'); + AddToList(nfcNumber, '0.00'); + AddToList(nfcNumber, '0.000'); + AddToList(nfcNumber, '#,##0'); + AddToList(nfcNumber, '#,##0.0'); + AddToList(nfcNumber, '#,##0.00'); + AddToList(nfcNumber, '#,##0.000'); + + AddToList(nfcPercent, '0%'); + AddToList(nfcPercent, '0.0%'); + AddToList(nfcPercent, '0.00%'); + AddToList(nfcPercent, '0.000%'); + + AddToList(nfcScientific, '0E+0'); + AddToList(nfcScientific, '0E+00'); + AddToList(nfcScientific, '0E+000'); + AddToList(nfcScientific, '0.0E+0'); + AddToList(nfcScientific, '0.0E+00'); + AddToList(nfcScientific, '0.0E+000'); + AddToList(nfcScientific, '0.00E+0'); + AddToList(nfcScientific, '0.00E+00'); + AddToList(nfcScientific, '0.00E+000'); + AddToList(nfcScientific, '0.000E+0'); + AddToList(nfcScientific, '0.000E+00'); + AddToList(nfcScientific, '0.000E+000'); + AddToList(nfcScientific, '0E-0'); + AddToList(nfcScientific, '0E-00'); + AddToList(nfcScientific, '0E-000'); + AddToList(nfcScientific, '0.0E-0'); + AddToList(nfcScientific, '0.0E-00'); + AddToList(nfcScientific, '0.0E-000'); + AddToList(nfcScientific, '0.00E-0'); + AddToList(nfcScientific, '0.00E-00'); + AddToList(nfcScientific, '0.00E-000'); + AddToList(nfcScientific, '0.000E-0'); + AddToList(nfcScientific, '0.000E-00'); + AddToList(nfcScientific, '0.000E-000'); + + AddToList(nfcFraction, '# ?/?'); + AddToList(nfcFraction, '# ??/??'); + AddToList(nfcFraction, '# ???/???'); + AddToList(nfcFraction, '# ?/2'); + AddToList(nfcFraction, '# ?/4'); + AddToList(nfcFraction, '# ?/8'); + AddToList(nfcFraction, '# ?/16'); + AddToList(nfcFraction, '# ?/32'); + AddToList(nfcFraction, '?/?'); + AddToList(nfcFraction, '?/??'); + AddToList(nfcFraction, '?/???'); + AddToList(nfcFraction, '?/2'); + AddToList(nfcFraction, '?/4'); + AddToList(nfcFraction, '?/8'); + AddToList(nfcFraction, '?/16'); + AddToList(nfcFraction, '?/32'); + + AddToList(nfcCurrency, '#,##0 [$$];-#,##0 [$$]'); + AddToList(nfcCurrency, '#,##0.00 [$$];-#,##0.00 [$$]'); + AddToList(nfcCurrency, '#,##0 [$$];(#,##0) [$$]'); + AddToList(nfcCurrency, '#,##0.00 [$$];(#,##0.00) [$$]'); + AddToList(nfcCurrency, '#,##0 [$$];[red]-#,##0 [$$]'); + AddToList(nfcCurrency, '#,##0.00 [$$];[red]-#,##0.00 [$$]'); + AddToList(nfcCurrency, '#,##0 [$$];[red](#,##0) [$$]'); + AddToList(nfcCurrency, '#,##0.00 [$$];[red]-#,##0.00 [$$]'); + AddToList(nfcCurrency, '[$$] #,##0;[$$] -#,##0'); + AddToList(nfcCurrency, '[$$] #,##0.00;[$$] -#,##0.00'); + AddToList(nfcCurrency, '[$$] #,##0;[$$] (#,##0)'); + AddToList(nfcCurrency, '[$$] #,##0.00;[$$] (#,##0.00)'); + AddToList(nfcCurrency, '[$$] #,##0;[red][$$] -#,##0'); + AddToList(nfcCurrency, '[$$] #,##0.00;[red][$$] -#,##0.00'); + AddToList(nfcCurrency, '[$$] #,##0;[red][$$] (#,##0)'); + AddToList(nfcCurrency, '[$$] #,##0.00;[red][$$] -#,##0.00'); + + AddToList(nfcDate, 'dddd, '+fs.LongDateFormat + ' ' + fs.ShortTimeFormat); + AddToList(nfcDate, 'dddd, '+fs.ShortDateFormat + ' ' + fs.ShortTimeFormat); + AddToList(nfcDate, 'dddd, '+fs.LongDateFormat); + AddToList(nfcDate, 'dddd, '+fs.ShortDateFormat); + AddToList(nfcDate, 'ddd., '+fs.LongDateFormat + ' ' + fs.ShortTimeFormat); + AddToList(nfcDate, 'ddd., '+fs.ShortDateFormat + ' ' + fs.ShortTimeFormat); + AddToList(nfcDate, 'ddd., '+fs.LongDateFormat); + AddToList(nfcDate, 'ddd., '+fs.ShortDateFormat); + AddToList(nfcDate, fs.LongDateFormat + ' ' + fs.ShortTimeFormat); + AddToList(nfcDate, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat); + AddToList(nfcDate, fs.LongDateFormat); + AddToList(nfcDate, fs.ShortDateFormat); + AddToList(nfcDate, 'dd. mmmm'); + AddToList(nfcDate, 'dd. mmm.'); + AddToList(nfcDate, 'd. mmmm'); + AddToList(nfcDate, 'd. mmm.'); + AddToList(nfcDate, 'mmmm dd'); + AddToList(nfcDate, 'mmmm d'); + AddToList(nfcDate, 'mmm. dd'); + AddToList(nfcDate, 'mmm. d'); + AddToList(nfcDate, 'mmmm yyyy'); + AddToList(nfcDate, 'mmm. yy'); + AddToList(nfcDate, 'yyyy-mmm'); + AddToList(nfcDate, 'yy-mmm'); + + AddToList(nfcTime, fs.LongTimeFormat); + AddToList(nfcTime, fs.ShortTimeFormat); + AddToList(nfcTime, AddAMPM(fs.LongTimeFormat, fs)); + AddToList(nfcTime, AddAMPM(fs.ShortTimeFormat, fs)); + AddToList(nfcTime, 'nn:ss'); + AddToList(nfcTime, 'nn:ss.0'); + AddToList(nfcTime, 'nn:ss.00'); + AddToList(nfcTime, 'nn:ss.000'); + AddToList(nfcTime, '[h]:nn'); + AddToList(nfcTime, '[h]:nn:ss'); + + AddToList(nfcText, '@'); + + // Add user-defined formats + if copiedFormats <> nil then + begin + for i:=0 to copiedFormats.Count-1 do begin + nfs := copiedFormats.Strings[i]; + data := PtrInt(copiedFormats.Objects[i]); + NumFormats.AddObject(nfs, TObject(PtrInt(data))); + end; + copiedFormats.Free; + end; +end; + +procedure DestroyNumFormats; +begin + NumFormats.Free; +end; + +{ Reads the user-defined number format strings from an ini file. } +procedure ReadNumFormatsFromIni(const AIniFile: TCustomIniFile); +var + section: String; + list: TStringList; + cat: TsNumFormatCategory; + i: Integer; + nfs: String; + scat: String; +begin + if NumFormats = nil + then NumFormats := TStringList.Create + else NumFormats.Clear; + + list := TStringList.Create; + try + section := 'Built-in number formats'; + AIniFile.ReadSection(section, list); + for i:=0 to list.Count-1 do begin + scat := list.Names[i]; + nfs := list.Values[scat]; + cat := TsNumFormatCategory(GetEnumValue(TypeInfo(TsNumFormatCategory), scat)); + AddToList(cat, nfs, BUILTIN_OFFSET); + end; + + list.Clear; + section := 'User-defined number formats'; + AIniFile.ReadSection(section, list); + for i:=0 to list.Count-1 do begin + scat := list.Names[i]; + nfs := list.Values[scat]; + cat := TsNumFormatCategory(GetEnumValue(TypeInfo(TsNumFormatCategory), scat)); + AddToList(cat, nfs, USER_OFFSET); + end; + + finally + list.Free; + end; +end; + +procedure WriteNumFormatsToIni(const AIniFile: TCustomIniFile); +var + data: PtrInt; + section: String; + i: Integer; + cat: TsNumFormatCategory; + scat: String; + nfs: String; +begin + section := 'Built-in number formats'; + for i:=0 to NumFormats.Count-1 do + begin + data := PtrInt(NumFormats.Objects[i]); + if data < USER_OFFSET then + begin + cat := TsNumFormatCategory(data - BUILTIN_OFFSET); + scat := Copy(GetEnumName(TypeInfo(TsNumFormatCategory), ord(cat)), 3, MaxInt); + nfs := NumFormats.Strings[i]; + AIniFile.WriteString(section, scat, nfs); + end; + end; + + section := 'User-defined number formats'; + for i:=0 to NumFormats.Count-1 do + begin + data := PtrInt(NumFormats.Objects[i]); + if data >= USER_OFFSET then + begin + cat := TsNumFormatCategory(data - USER_OFFSET); + scat := Copy(GetEnumName(TypeInfo(TsNumFormatCategory), ord(cat)), 3, MaxInt); + nfs := NumFormats.Strings[i]; + AIniFile.WriteString(section, scat, nfs); + end; + end; +end; + + + +{ TNumFormatForm } + +constructor TNumFormatForm.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FGenerator[nfcNumber] := -1234.123456; + FGenerator[nfcPercent] := -0.123456789; + FGenerator[nfcScientific] := -1234.5678; + FGenerator[nfcFraction] := -1234; //-1.23456; + FGenerator[nfcCurrency] := -1234.56789; + FGenerator[nfcDate] := EncodeDate(YearOf(date), 1, 1); + FGenerator[nfcTime] := EncodeTime(9, 0, 2, 235); + FGenerator[nfcText] := NaN; + GetRegisteredCurrencies(CbCurrSymbol.Items); +end; + +procedure TNumFormatForm.BtnAddCurrSymbolClick(Sender: TObject); +var + F: TCurrencyForm; +begin + F := TCurrencyForm.Create(nil); + try + if F.ShowModal = mrOK then + begin + GetRegisteredCurrencies(CbCurrSymbol.Items); + CbCurrSymbol.ItemIndex := CbCurrSymbol.Items.IndexOf(F.CurrencySymbol); + ReplaceCurrSymbol; + end; + finally + F.Free; + end; +end; + +procedure TNumFormatForm.BtnAddFormatClick(Sender: TObject); +var + cat: TsNumFormatCategory; + idx: Integer; + nfs: String; +begin + if LbCategory.ItemIndex > -1 then begin + cat := TsNumFormatCategory(LbCategory.ItemIndex); + nfs := EdNumFormatStr.Text; + if nfs = '' then nfs := 'General'; + if NumFormats.IndexOf(nfs) = -1 then + begin + AddToList(cat, nfs, USER_OFFSET); + SelectCategory(cat); // Rebuilds the "Format" listbox + idx := FindNumFormat(cat, nfs); + SelectFormat(idx); + end; + end; +end; + +procedure TNumFormatForm.BtnDeleteFormatClick(Sender: TObject); +var + cat: TsNumFormatCategory; + idx: Integer; + nfs: String; + n, i: Integer; +begin + if LbCategory.ItemIndex > -1 then begin + // Find in internal template list + idx := NumFormats.IndexOf(EdNumFormatStr.Text); + if idx > -1 then begin + nfs := NumFormats.Strings[idx]; + n := PtrInt(NumFormats.Objects[idx]); + if n >= USER_OFFSET + then cat := TsNumFormatCategory(n - USER_OFFSET) + else cat := TsNumFormatCategory(n - BUILTIN_OFFSET); + i := FindNumFormat(cat, nfs); // Index in format listbox + // Delete from internal template list + NumFormats.Delete(idx); + + // Rebuild format listbox (without the deleted item) + SelectCategory(cat); + if i >= LbFormat.Items.Count + then SelectFormat(LbFormat.Items.Count-1) + else SelectFormat(i); + end; + end; +end; + +procedure TNumFormatForm.CbCurrSymbolSelect(Sender: TObject); +begin + ReplaceCurrSymbol; +end; + +procedure TNumFormatForm.CbNegRedClick(Sender: TObject); +var + nfs: String; + nfp: TsNumFormatParams; +begin + if FLockCount > 0 then + exit; + + if EdNumFormatStr.Text = '' then nfs := 'General' else nfs := EdNumFormatStr.Text; + nfp := CreateNumFormatParams(nfs, FWorkbook.FormatSettings); + if nfp <> nil then + try + nfp.SetNegativeRed(CbNegRed.Checked); + EdNumFormatStr.Text := nfp.NumFormatStr; + SelectCategory(TsNumFormatCategory(LbCategory.ItemIndex)); // to rebuild the format listbox + UpdateSample(nfp); + finally + nfp.Free; + end; +end; + +procedure TNumFormatForm.CbThousandSepClick(Sender: TObject); +var + nfs: String; + nfp: TsNumFormatParams; +begin + if FLockCount > 0 then + exit; + + if EdNumFormatStr.Text = '' then nfs := 'General' else nfs := EdNumFormatStr.Text; + nfp := CreateNumFormatParams(nfs, FWorkbook.FormatSettings); + if nfp <> nil then + try + nfp.SetThousandSep(CbThousandSep.Checked); + EdNumFormatStr.Text := nfp.NumFormatStr; + SelectCategory(TsNumFormatCategory(LbCategory.ItemIndex)); // to rebuild the format listbox + UpdateSample(nfp); + finally + nfp.Free; + end; +end; + +procedure TNumFormatForm.EdDecimalsChange(Sender: TObject); +begin + if FLockCount > 0 then + exit; + ReplaceDecs; +end; + +procedure TNumFormatForm.EdNumFormatStrChange(Sender: TObject); +var + nfp: TsNumFormatParams; +begin + nfp := CreateNumFormatParams(EdNumFormatStr.Text, FWorkbook.FormatSettings); + try + UpdateControls(nfp); + finally + nfp.Free; + end; +end; + +{ Returns the index of a specific number format string in the format listbox + shown for a particular category } +function TNumFormatForm.FindNumFormat(ACategory: TsNumFormatCategory; + ANumFormatStr: String): Integer; +var + i: Integer; + data: PtrInt; + cat: TsNumFormatCategory; + nfs: String; +begin + Result := -1; + if ANumFormatStr = '' then ANumFormatStr := 'General'; + for i := 0 to NumFormats.Count-1 do begin + nfs := NumFormats.Strings[i]; + data := PtrInt(NumFormats.Objects[i]); + if data >= USER_OFFSET then + cat := TsNumFormatCategory(data - USER_OFFSET) + else + cat := TsNumFormatCategory(data - BUILTIN_OFFSET); + if (cat = ACategory) then + inc(Result); + if SameText(nfs, ANumFormatStr) then + exit; + end; +end; + +function TNumFormatForm.FormatStrOfListIndex(AIndex: Integer): String; +var + idx: PtrInt; +begin + if (AIndex >= 0) and (AIndex < LbFormat.Count) then + begin + idx := PtrInt(LbFormat.Items.Objects[AIndex]); + Result := NumFormats.Strings[idx]; + end else + Result := ''; +end; + +function TNumFormatForm.GetNumFormatStr: String; +begin + Result := EdNumFormatStr.Text; +end; + +procedure TNumFormatForm.LbCategoryClick(Sender: TObject); +begin + SelectCategory(TsNumFormatCategory(LbCategory.ItemIndex)); +end; + +procedure TNumFormatForm.LbFormatClick(Sender: TObject); +begin + SelectFormat(LbFormat.ItemIndex); +end; + +procedure TNumFormatForm.LbFormatDrawItem(Control: TWinControl; Index: Integer; + ARect: TRect; State: TOwnerDrawState); +var + s: String; + nfs: String; + nfp: TsNumFormatParams; + idx: PtrInt; +begin + Unused(Control); + LbFormat.Canvas.Brush.Color := clWindow; + LbFormat.Canvas.Font.Assign(LbFormat.Font); + if State * [odSelected, odFocused] <> [] then + begin + LbFormat.Canvas.Font.Color := clHighlightText; + LbFormat.Canvas.Brush.Color := clHighlight; + end; + if (Index > -1) and (Index < LbFormat.Items.Count) then + begin + s := LbFormat.Items[Index]; + idx := PtrInt(LbFormat.Items.Objects[Index]); + nfs := NumFormats.Strings[idx]; + nfp := CreateNumFormatParams(nfs, FWorkbook.FormatSettings); + try + if (nfp <> nil) and (Length(nfp.Sections) > 1) and (nfp.Sections[1].Color = scRed) then + LbFormat.Canvas.Font.Color := clRed; + finally + nfp.Free; + end; + end else + s := ''; + LbFormat.Canvas.FillRect(ARect); + LbFormat.Canvas.TextRect(ARect, ARect.Left+1, ARect.Top+1, s); +end; + +procedure TNumFormatForm.ReplaceCurrSymbol; +var + cs: String; + i: Integer; + nfp: TsNumFormatParams; + data: PtrInt; + cat: TsNumFormatCategory; +begin + cs := CbCurrSymbol.Items[CbCurrSymbol.ItemIndex]; + for i:=0 to NumFormats.Count-1 do + begin + data := PtrInt(NumFormats.Objects[i]); + if (data >= USER_OFFSET) then + cat := TsNumFormatCategory(data - USER_OFFSET) + else + cat := TsNumFormatCategory(data - BUILTIN_OFFSET); + if cat = nfcCurrency then + begin + nfp := CreateNumFormatParams(NumFormats.Strings[i], FWorkbook.FormatSettings); + if (nfp <> nil) then + try + nfp.SetCurrSymbol(cs); + finally + nfp.Free; + end; + end; + end; + SelectCategory(TsNumFormatCategory(LbCategory.ItemIndex)); // to rebuild the format listbox +end; + +procedure TNumFormatForm.ReplaceDecs; +var + nfp: TsNumFormatParams; +begin + if EdDecimals.Text = '' then + exit; + + nfp := CreateNumFormatParams(EdNumFormatStr.Text, FWorkbook.FormatSettings); + try + nfp.SetDecimals(EdDecimals.Value); + EdNumFormatStr.Text := nfp.NumFormatStr; + UpdateSample(nfp); + finally + nfp.Free; + end; +end; + +procedure TNumFormatForm.SelectCategory(ACategory: TsNumFormatCategory); +var + nfp: TsNumFormatParams; + i, digits, numdigits: Integer; + data: PtrInt; + s: String; + genvalue: Double; + cat: TsNumFormatCategory; +begin + LbCategory.ItemIndex := ord(ACategory); + with LbFormat.Items do + begin + Clear; + for i:=0 to NumFormats.Count-1 do + begin + data := PtrInt(NumFormats.Objects[i]); + if data >= USER_OFFSET then + cat := TsNumFormatCategory(data - USER_OFFSET) + else + cat := TsNumFormatCategory(data - BUILTIN_OFFSET); + if cat = ACategory then + begin + nfp := CreateNumFormatParams(NumFormats.Strings[i], FWorkbook.FormatSettings); + try + if IsTextFormat(nfp) then + s := 'abc' + else + begin + genValue := FGenerator[ACategory]; + if nfkTimeInterval in nfp.Sections[0].Kind then + genvalue := genValue + 1.0; + if ACategory = nfcFraction then + begin + digits := nfp.Sections[0].FracInt; + numdigits := nfp.Sections[0].FracDenominator; + genvalue := 1.0 / (IntPower(10, numdigits) - 3); + if digits <> 0 then genvalue := -(1234 + genValue); + end; + s := ConvertFloatToStr(genValue, nfp, FWorkbook.FormatSettings); + if s = '' then s := 'General'; + end; + LbFormat.Items.AddObject(s, TObject(PtrInt(i))); + finally + nfp.Free; + end; + end; + end; + end; + CurrSymbolPanel.Visible := (ACategory = nfcCurrency); + GbOptions.Visible := not (ACategory in [nfcDate, nfcTime]); +end; + +procedure TNumFormatForm.SelectFormat(AIndex: Integer); +var + nfp: TsNumFormatParams; +begin + if LbCategory.ItemIndex = -1 then + exit; + + LbFormat.ItemIndex := AIndex; + if AIndex >= 0 then begin + FNumFormatStrOfList := NumFormats.Strings[PtrInt(LbFormat.Items.Objects[AIndex])]; + nfp := CreateNumFormatParams(FNumFormatStrOfList, FWorkbook.FormatSettings); + try + UpdateControls(nfp); + finally + nfp.Free; + end; + end; +end; + +procedure TNumFormatForm.SetData(ANumFormatStr: String; AWorkbook: TsWorkbook; + ASample: variant); +var + cs: String; +begin + FWorkbook := AWorkbook; + cs := FWorkbook.FormatSettings.CurrencyString; + if (cs = '?') or (cs = '') then + cs := DefaultFormatSettings.CurrencyString; + CbCurrSymbol.ItemIndex := CbCurrSymbol.Items.IndexOf(cs); + + if varIsStr(ASample) then + FSampleText := VarToStr(ASample) + else + FSampleValue := ASample; + InitNumFormats(FWorkbook.FormatSettings); + SetNumFormatStr(ANumFormatStr); +end; + +procedure TNumFormatForm.SetNumFormatStr(const AValue: String); +var + nfs: String; + nfp: TsNumFormatParams; + cat: TsNumFormatCategory; + i: Integer; +begin + if AValue = '' then + i := NumFormats.IndexOf('General') + else + i := NumFormats.IndexOf(AValue); + if i = -1 then + exit; + + nfs := NumFormats.Strings[i]; + nfp := CreateNumFormatParams(nfs, FWorkbook.FormatSettings); + try + if nfkPercent in nfp.Sections[0].Kind then + cat := nfcPercent + else + if nfkExp in nfp.Sections[0].Kind then + cat := nfcScientific + else + if nfkCurrency in nfp.Sections[0].Kind then + cat := nfcCurrency + else + if nfkFraction in nfp.Sections[0].Kind then + cat := nfcFraction + else + if nfkDate in nfp.Sections[0].Kind then + cat := nfcDate + else + if (nfp.Sections[0].Kind * [nfkDate, nfkTime] = [nfkTime]) then + cat := nfcTime + else + cat := nfcNumber; + SelectCategory(cat); + SelectFormat(FindNumFormat(cat, AValue)); + UpdateControls(nfp); + ReplaceCurrSymbol; + finally + nfp.Free; + end; +end; + +procedure TNumFormatForm.UpdateControls(ANumFormatParams: TsNumFormatParams); +var + cs: String; + i: Integer; +begin + if ANumFormatParams = nil then + begin + EdNumFormatStr.Text := 'General'; + GbOptions.Hide; + end else + begin + EdNumFormatStr.Text := ANumFormatParams.NumFormatStr; + if (ANumFormatParams.Sections[0].Kind * [nfkDate, nfkTime] <> []) then + GbOptions.Hide + else begin + GbOptions.Show; + inc(FLockCount); + EdDecimals.Value := ANumFormatParams.Sections[0].Decimals; + CbNegRed.Checked := (Length(ANumFormatParams.Sections) > 1) and + (ANumFormatParams.Sections[1].Color = scRed); + CbThousandSep.Checked := nfkHasThSep in ANumFormatParams.Sections[0].Kind; + dec(FLockCount); + end; + if (nfkCurrency in ANumFormatParams.Sections[0].Kind) then + begin + cs := ANumFormatParams.Sections[0].CurrencySymbol; + if cs <> '' then + begin + i := CbCurrSymbol.Items.IndexOf(cs); + if i = -1 then begin + RegisterCurrency(cs); + i := CbCurrSymbol.Items.Add(cs); + end; + CbCurrSymbol.ItemIndex := i; + end; + end; + end; + UpdateSample(ANumFormatParams); +end; + +procedure TNumFormatForm.UpdateSample(ANumFormatParams: TsNumFormatParams); +begin + if (FSampleValue < 0) and + (Length(ANumFormatParams.Sections) > 1) and + (ANumFormatParams.Sections[1].Color = scRed) + then + Sample.Font.Color := clRed + else + Sample.Font.Color := clWindowText; + + if IsTextFormat(ANumFormatParams) then + Sample.Caption := ApplyTextFormat(FSampleText, ANumFormatParams) + else + Sample.Caption := ConvertFloatToStr(FSampleValue, ANumFormatParams, + FWorkbook.FormatSettings); + + BtnAddFormat.Enabled := (EdNumFormatStr.Text <> FNumFormatStrOfList); +end; + + +initialization + +finalization + DestroyNumFormats; + +end. + diff --git a/applications/spready/spready.ico b/applications/spready/spready.ico new file mode 100644 index 0000000000000000000000000000000000000000..af0851c77071377cf524cc6483a0e6c18ed274fd GIT binary patch literal 132106 zcmeFa2Ur!!(myMbZw8mWuB)#1zI)&I`R^x>wcXRx)2F6?Rn^ti-Ln9I0B`{K4*}2vsR96C z4&_m(&(|mLpu2(qz{U0XI{O#^a3Gw)h06uOAfEX%=+q1+1 z02~woxTdNsyMG_$KB(#aXXT{N!*^lAgMV7jDI5Mxd68y|+fTE#XFBZ;w2|L^_dCmIY1l{;yVvm6m#LV9{Tarr=4 zL2&QZ(T|>n)#Eh96|2c20<$_ts(}};@}&2V6^ZCh8Qk6~wby%g>Uw7OGu+ML`2`wTZFAF1k7P1EVkBYkR4 zd|OMQ@+8M?&Vi}(DtBW`nz2z~*XdctdB^~NI5~{U72hvSeER^^k$rkH z*@G&?-4i@-5X4yL*yRAcyFm;H`Vh(>EEN4EauUEl+xWjz*i+xCrn4fsWHz-Rp|Vt( zpf|E%rq=0iSe&)L_pR+IDy zZM%(j-?gt^0B;YzIgNYw7j%ZfYA;PhT}{_wu~os#R7^9TORzP)bE0 zM(sj?++e_jQq#2EuD&yXNgr~lmYhB#Ku(wVKHtTGfI{qaRjL520915`P%*v(nN&rQn4cFd&eX#iZ7Cc({cPw;eA3X0JFLjC)2vE z1P9G$DT>#^51@!o*%(U>oC@G#V5cg|A0H@>Cef(|FmMWyfGCMSDZZc8P=8g8{S_K| z1bvZcat#6gO~o1mULg#aKd+Di_ARJX${^tTXgsNG`%*ysOSQILC12$<_n_ zv)S_)^S*L`q@1=n#+*8axv-xL3lVP;@{%J(&kzPZllBR$Tn;RDN}L1OH6<+XoDO4o z3eMt49l+Iy-f~c7VDedikGJSMCg`&qr6zahIH8g(6Nyx|8P(DDGXb^dEE97^L@n9` z)q+}q7IHzgVQ(~#$;8o&^0WMsktFAF=%vMM7#IQqh*9iVx2~Dh-=2xoOO|pnJ~-F! zfwdpAxXMPt0Bp>0ta~a_^Wi!{w9ykfB6%^uq-ji`g_p6j1oWFMSqg68<}D60qDN_) z;ui529zA@mrcKZ#{B*C7OOhFwd-7l#-!Uvo(=kyktjA%7K#@9*{UAwEWWEi46AAR6 zPSX5&jQj*jqka+N0gRWMM@eV0maFTs-X#Sqr1EMKypUy57YlzBVQ6@V?#y%Y~->BkB7${oxJ%s1gBj6k(K zkw*5$&0{;@WNv$-?1|}_=mY1i@a~6=*l$}YRP$kXESlq|cVe7Ws1Cz!>lni7tiT{p zc%mJbRDZi_jY%AQ+Tbu;W4GP%s0vGsX-2M zQheErBt67Lb0JuKvV?*dh^#fk_WANVm)>279iLf6WT(jEsoyXPBo=&z=)5Htf2t!B z$-^G0*dLN*!*q*u0)Nd*)GC#MRPymXf+xIDC455HcMf+NC2O7t?*sr{q2zvWg!uka;i8gWQ0&vW~X0wzj;s zwsK$g4Ld1aU0idEOfG&$+NG@*#g0qv$+hJ>V{Y$l>|2HiiadDnpgut}_(fZd^MW7n z-n55?U`bhydIPz+Ng)BQ^|g&-rUx6A>x7RQ(~P5nR3jOUEb&UtJSrXWNpZFhOtT20 zFstUNx;O#wbb9Svz^EcmPZ~eXW6O9`T{1s9KmTxX{$YUv@?ur8IcaAF*32x9@ej_7 zB?~m}lds(MZWMnSP*6XBO=#q#CXK>E^>O)lzGoAE|E?}B>BhY$*0{oDp2VR+s$?2x z4C%OuLqFwcnfsYt+>suY$3P8uR88V`?X z@K#6=U;0su`_agwW;w~op=y(%`r5~Vfo6wpwh{52Dl*>g5V|r|$;`ccZ)W)})rOyQ zW~1w+vYV1f4CF(RBKGA1&TXuXA>YGmYy11$$AtM#p;gJaRq49V(ebO&@e_y6hMXB9 zHKeGt+iZB>+?$|)_Y%P8(j4ee81N|F5t^Y4Lr@dyVe+B7)YDrIb{&&Ez5ixvP>8e)QSWE3<_dH7PBWtA&TH~>*(l> zwDGepb_=I1dX?*s23fq{?<#C^u5NCTRi&zTq8uUSpd&M07-=x~_~G#@u2QI{HE|@E zR}n+k&T?T~D(g5BASdU1h2pq>%^7LNXC;>%v7&Cb)G2196&Fj+QwC%|ELTL;5 zyze94nZ7rQIZ0ifSAz43{Z&Lem1PKJ_9I?mf`t(2uJ;DjZK8D+VM1x857^uNGi(z0X*G3ge}Y9BN_t~1N70%gFJiN6SVER~6o(r8ihpawZm8QwSYu_0+zeeu$2;Da; zq^KM=p#rWi^j57*e?l)9IJW7j9E8w&a7Ng6yj9`~9j(}@u$Dai+1dFsY!B{LwjfRQ z(d}gTb9gv>oQhg<_<~Jq-Tu$ckFGU(VN6+}9$uCk7v9jgfy~vwYgBAs9Kf;dfhE91gV>?$1;Ddv-ExDUvKS;k?tCCIDXCUs=abjF z*wG!szGpMYxrsQnVxDF@{`R1ucws^uL7TMuV@CxhROLf@+)$2g#;;57;Hcu(U5%JQ5r|m6)eog$+yQF ziCYG|n)t(Ff?_S6T(_A@eAK9Vm&<99Fda*=vz|9pOHV z*z#+lccKidi!uZ{Yf2AEAAT(_Dn)r$xf#jU6B4obDbd+&@}A0maAr$F*hqbqH=O|} zIG&ERGf!6)8k`~++CsB+(Av^*x`bE39kZoFuZ4msdR*#(V^wcAXE{5okI|e{m+Itt z?>3A0ht?%`1H|Ii02vprSYYq)JE|#zMxk`dk(w|=lyh}k*Czs8eohc&b+)UwxcbdN z6NkRw+JOC)r8yM?U!@J*oT&q_1*?~p*dT^oFdY&1w8{dSpcdk;q_q!a@-1oBgw)OP zy|@6rUpM))lzByj-NH!l)!vbSNfojAXKt_4mX1^AQ zqVj~K{82&bs`Qrlaip?RrXtNQ`=Tai7C(l9?xTH>2If~?#BPN2LYx19_=>2wSL;1X z%l-&-EDg&Wji!gM1QMTq2ot$>Dg(>r7{+tTTsBO1Mytm+PFyH<^288$_J*HabX~3| zXS5t-ot+&BOdiH299)xz}L;d;mf;xKD}S*toLk6L4?8rPXK##)ZP>fh+o^W0b3jGw~TujyAo#ZO^MT zMHWX+*Dxco#-OO8^2j0m$Of*q^2faMJE)!rT9>zdle!xR`ijE6b|wwEL`3eCCSSN) z8F&Rz$^JI;2R32eQCTrP`KB3*nz)9d3EzWB zB1Dn`7!NX>>MnR3#}*hW)RB~APicLBe%0;Tr?a9=b<3q{kr;BvNiM%;#w?j=B%2XB zJ1takQ>&a+h?{jE{7$G1a4KWFJ10lSn|)Kx?pyA@ztX|vg9RN zxr?`=s-BNxeg{P=OXlgtynqI$vi~F%k|Kat(R9fI1 z<;j~Be1S-=>zO@CBe&x`!0K!6txTORt3xO0jx@RL9J#)3iWH8ieqSGFp>S=Jhm@3z zcwg_7dQNm)$$hkJaLV&f8$Q%Uwq{iKmnvd3;uEOr$RySTF0WCI2C)+9-L9$>n#vb_ zbR>JV(X>L~EQvAB;1jivV&eR+)!*}x2 ztST%B!IkP>qXhFs#4*psmlrWMKJ_*%-@RiPN@cKq+(9#)l|HFJ#cv~K3A>71ZaQe6 z0v;7KGaAPtC@rol4;)d#P7qnYL>8PfkF!h*_@3LQnUcgn9+pX0O3#{6?QQczo+v)z zrd5WI(3X^Z!bFZ0@ZJ^leyvb6?t3g=-s_+f$5mN6N#_|_fP}zVEiPX4hN@uDdW(MB z`=RQRW`1>{B6j-gY|ylFq#(Z^-5h8_*J!*XiX{XnY_PO%R!)l00^V_uhT ztVQ#pz8;33Dve1vjdmiHua^C2S~&!s3Tdem5#)lLyG52&9Up}5(ZBFWK~9cqhJe+0 z5Todo5f9=d1z$}CX(y=98Dqx|oW=zB7o-u5j^p8kVpnmiyab?|x&)LyLeZY!j{57&ImLtWb3(YQ-A@Z#$zsVe zi zhK9Dyn8%D1*8r!E4+AB9p29PmE-cq@E7$NVUayzuTZ8*q8ymMrh6<=A$y%c;eXf1V zO7T7%o-0yxGR;wMF!)aSRDQ zJN96_pcEs&ICnbv`W-ExXv{m3WOM3~n7l zBVNEyjzFhu-FT(;zT#PHe&xa1x?qVLhTBg!Vvm+f##u{-wUy>=Mn( zBa;1X9j~%Dk}D{ysemgviDfqdVvi5?WWLvtTw!u-oe#>!KXiPkJA!D^%#~onVc zo%A~Klp{4xvspQ@?)7uEKG0taQ@IjrE+l6V(;-ENEwRh$!vnf&PbE_*i`aSB44?_U z^;Em*%yRR6?n0O86wj#h!q>#QZmUnNkIyUQASku$>^5GC`RwcW8%!Wd@hr@45LdhQ zMuM3mQF5S=z#uK{lYD)GyNS=G^sw4bN1DKuRTYVl>6Rg5-FM2T7h8B6d_!iEH*o;u zW57+{!YRjc@hDSW~WoTBTeUdl!@hFA31ag^&R$es= zZ~A;$&6$@to;U{OY}NCCB{%WS=WQcZk=;V~Nv^06Y#OndCa zJAJj@33kGxu|+qP2gyaenyshy+3q|SIe*bU>RxLNo6CN+%cUEQgQ}OKQ0#tl*AAv9 zZcN!($?lbhY(?YL+&GGa<>V53%A8 z>d#H9a3a$y_dkiU2#j9g0AvmYs~$it6Q7^BBOw@JR7jCXW>2*(hS&&Ykuh%>aPuwx z^a0ps-xS)Zok;Q0Zd|MMl@gKhmDh9r_(GlcFJ72Byx_N4yt$${K7{gEIjG|?|2$k< z(*Wb7AA!`3%lLBoOI7dhA~JGHvB&jfOY#D*78JiH`J1j%Sgz7kSHG zXebv$td-l_3Af&U(iPpm-KDBQ8!G1VzKYncFT$wgq(zEt=mT-j!6G(oH#mXS)So07qh=>Sm7DHJj+w&vJ7HcXnr2Hh(hi66zAUz_w; zpHa;z*y1w2r20OV=!SSc-T0L(?dQ&bU&SyGLuzr(_UfUiL^cg?a+0zSj_x z=D6Qa)kZCkGf=;K#fCRTrKQzZ;@M2y7*MnC~D-~<9Mz|^dvSnH0QR5B`IUp%c?(DS)w7Ni)lj9|}&*I^x8 z==_N;bWgR?KKAXP@m-{v?9xPl`gQii78&b&ljK=7$sV7>Tdj>Clk( z5?lA{uQ>%K4Za=mctz7!v~;BHJu;cs>AwA7sI{FJu1@)C1~ccY&9)m5XHBy&5f5EI zn9v`_o=gbGh(KP)q<2`~<|AbE=jXijh-6sn84*EL>+LWK?fq-HUd{%ldUflpTWytF zq>71R{+koW;$C8>M-dQfQr5^F@^9A+xXT{GXCu2>WbklpgiSf6W@S6@`iRt(ouee7 zQFsjly$+|Y9t_EMapGPo3B*EG&yAn7JY)GJ$Iro=dBDBu@T5hAdWI-kyIpe-ug7>R z##^IQlYwRJb$LA*y5|IdI*8}Y`_x6L(wh$}+flIz{rsH=x!xws&=!VQ6p3|jPs#Bkk}fF`GVrWO`uEAqE!X6I(7~LAhYxK zYYndihw!=Ne$>mO=qm!<-gv*WH{tcBEQ+apKimEw=C(F9q*s-#ry33*#i3t(UCTy} z>0-Ko2LR-09mjY z_-1xJb`aOar)O>$%-mOPfusCdDN5hkX4+dWT;(daZRb%Sw5B8|mZmq&tie?~S?tDU ztxP%zuUv!0P5EX9;!DUvN8G#NBE(jGL`sil&-QDWnQV?fh;8^VAhHm~?U0Ah@Mbz@ zD;rmJQjVdTFZV8wIVX**)Ry0^v(hXK16|>kY8z!ShDxLsEk_IT*Ezhz$#dTDn&?Fl zyG6LiV5RmPB&n$7>@79jK+0c3x8&rn&I?E$urWZkYZ|Q#F=}w~s-~$$JBRlpBY?<5 z`RJRHsCSK6NZ#6r&IR)0EgHoOUP6z#^gnW6%sJNMBqKA!o5%h7ATW>U582(6_-V^0=(*XG zyFBlaZs_}~%$55G6(tE6H)uQ>CNX}|?av(%w2m1^LG@54UgS|J zqd=8$3_Tq(T#XE0Qavs_E6>rQXB4uSP9r+pkjC{Zzw$hnXHiL#-QN0gt z*2V%(;`ERvGLzsV8=nTpmvt2{*1VrBxZcR6rXcufldP@ct3_WKc8cGQ!%Y%IpSuk(TEj|P$81= z54_KNggpuI<&7DM?WDOn z!lrGXSz1b<)^w_w0$(AakaK#0IN@Lsea1seF{IQMV#Y76`~K~C9dz3v!}{jF&e^$7 z$2hYX6X?j_FG97LJ+Rg!BahEu zLu6z=B@WxKnf2px_i68&VeJz~W-@uwUze+kxHUY~&Exfs0y4d)Tlw8nJ+=t6ymy)d zP059Javz9!vMuqWlg~iLKzL)Q%&s>Zt4R@%Pf9i{yvWivP9SSJR^(LOJMP6e$%JM)oXlOSxAvcA}GEfOJHgskgF4)A>+#N zQE}*r@^W3H1jmPKs%S=DSu%49>-2{1)zFF zH1^NmJ*`(-e8{3<8u2E(q{4ENsL-a0NKHdA^liuEdzaa&J=yQ%Vlmj%&om?kdu4mo zl1oA0yHQ^mE}NE-L(d$mjvykc5LxOxTRbv+^i<#-gTAXSCIy!|%^@>|IbJq@ToZg`pEgHdLfh*x1MOr-p#vD)t*V)#s5~iu)s^{#>a$baROs+9~(Jd z!aLu0L?R0T#F8CHpgANP=}1K)uu#imVdD^&;jJU9_2tVh-O zx!=C>nokIEjoRN5N0pmlt1DnK*uYW3H9Kf_LtM4|?kP**;Bq%-35@ zLdlSwJ{=mA7AO^$B3{+6aZ=vIk-Bx~wW%DNvW=U@1B^-PG)n~;vu2f)V#N9rC^G2Z z?&||B6jfm9P#MR+e1L@rHsC+oX zmKVD@ahQ$wg4@CYDCB_MW_oT})uGM{(a(X~aOoJPDRtQW_YGAoswu4PU`D!9=c^nt>Y<#z3omJWw>U@3J*;+a zIpO6UG7xsOko4y@%W3X^S>ob32k&mx)MCKm&!13%; zbq=fieQ^O-B1vtMNPEM#rEqK#2Z~c-Y>stoL$EX+vMoc`#9itZvKVXTwt+UR2=cY0 zT2b<4*0k}>CQ4Z-+9uZFb(>KM^W?g%lP8<8wVb=!obsW*Rx4SHII?#|p|ZW%${^;- z^OCA!8(&1(`ZJTYDUtLj1?>bnT+{*Klv2VLQGwUzwIn>!zN%qvae zm$Ir7V@wdf#-$IreDbgh76uH_M>ttN$raQVtC^T@7w$*5U~X3HTrUyrRVJZotZy^U zF>QUzY&*EEgnvynz2b^iRiG&Aeq!(Enux;aJP6#>8fMU&a(RT?kD?nHUEp~HmFQ*ku~3||3eLzKa3 z3vD#_dilHOttoLQ=gHCW#f}^97B8v=uVyaDF_RSt@=o-nv_{_S##POIVs9BKrfE^? zTW5bgJ}Kk5$#Ye#7o_;;w!Q+oa>M1(HgAm-Pa?)u5l$^;;N{eXW<^3owFG2_d|fn{ zw^F-N^_MnzQNuj0b6o`Go_U>oVye?tB#AkTm6_b+!nnO%#K@;3i&59~mneXf498Xt zZYkDEm<+piza^L0%Jw`1IJdC$ZLL48s+>Es#=FHd*DM(wG$s5YZb?|VyVNfA*_O=g zz?M^hY0|tmH~vY00dT-SUP9u>Bdb*ugYL>uJ5?QlSZQq($r&rB4_TReD^f^cq=H*l zU@5!7Uy=AI^3pR3jGzcqnpCgG!hx2Wbd&`<$&12Z#r{n7Q;q3Vtn}SWKugLM;;iIN z7F0~ple;o8rCwTrhJ23=Vm}z*0Mb-N_q=CZEk|7sVbo+Nc|{N=`YV@P$X%qQP7oux zvQJM^hp`$0>FVrRrrR9zDx-K8c)AH9-EOQ7+;W|t5BM*z{O#(>65JH!48NvGrO3aBpUj>pBvcBfNYEX!@Hgy zP`IQ=8j4X!0VBhG16MyzAAKoIk?I(fYD`Z}bd7qyu{vEL3d17p65P#({fn%Gu1X?pMUy&(?p4I&+Pa!tx5}ia zj|e2RKg%w}R%9@WKgCx59;>Og`NVYB)^<6>$5d(vk8wBbEt#3KU?Hy-SYNvV@|rUu9MHVy%I&oC?@{|9$vJ)2=*Ii5rqnlQsP(V2 z#dH#jr@dRoz}OD9z*(aJX*RB5OBJRaQcBut?s<)T-YM;`x&!PN@c&0Z!; z922EMV#u*lYcSw*e3+-n*xQ}v- zvK4DmP`UCUZK(*>GR4h7h2_w|kAwY7(Z+Yqh9!BCm|D=*bv;+>_rcn1#1!QoPlzx& z0ZojLti2k}wjc5Pm`M}D=jPA7NPdm-o`QvP%|eSvjEgnnCk*U(L$<{68-=#%?0)Jj z`#VV@d9;A@*E|%%l8MhZ$|5|rAnyu816r=jj)Ouj;YM#72nG8FT#p^-{osj_cYvN4 zS;!F}*M>@Cl|T)=jqkm#>5(DD<(yd6AB+7QBR?=u{R-m#)CHzP1dy9b4=qBTzkw{F zP0Rmig>_U2^bW~MS*#hGr#RDOQil-E3m$n8`ON922t#AD2b}?)bI<&lSSzy( z5(Wk=8{OK+Y}&CXTLQe4^X$!GCTNMWI*62IONDcZ5I1l$z%x9zZDavgLAXcpU^KB3( zD=M+gnOlvG%?|_O*kgH+5olZuAoB|X>dV>&-De*mDg?;$$a3{@ON_CqOET{wplzIp zBS$P}DP5$3(L>8)iizH6-be~B-d4;Rw^hV(txOEZij`YJolX=MddH7f_qw(c?j*e{ zQwy^XTZ&02(BP!(3&o3OIejf!*^7e-i^)b;QqJsstZm(6tPU$^cd_x{sQ`eDH}HNa zvkXf?HKM}TAr-VnL6Wlw^v#rJc0YBaZ97_E?tqSNU!e9wA?n(Q+gvS! z4l$3h;ZNIH@5}QfjHvlw#xQxRx&F|msaJY)#6l}8Y4RcN8`|`PS05Q16wjh{cPrt= z>bN$G8PNGy_dGu8EqSF?LVjYEtu9i|@AV4Xan9t&fwr88m11Z(uPQZ2c_|NRzH0`w zW~j{Nb|Af?AT5JRDOb!$@7PY8>;9m$oGUGg< zK$+=0kfp~;Cyq;^tl4h%KovC5PbEQO!`KZT-X|pvnCQoo3yY2x%&fO!;AN2za4NC2 zh9L7JoY?^egq1=cNq*p4^1ywO2hV$=)605ldzIWp=h-?Za{T;f%$CvXiwHu%UB}LS zoMFZR{f62g0$`q34WAs&mNML^i=T*+#P^Rp|MYbc>KKzv6UFG@DaFn+1CNb$FpA7- z3ZXHL!k48W+`VG=_ki)VJ z5iY`Bd50;$*)m}|kZ2*nslqCPQQ4W=vC%lIY&@@FnBSn++7Qo|vpT%Lbraw@EpcAH z)q+0IQ(vxOGpXPiaUQVg%Yrymv|kq}ij0)3E@E$1PJZ68eM~NYHF9MGMymYah6Ek7 zJuB$$QQUX5=w*(U{XJck3ZeXNK!lcosa-5RPLlOJKXYK*^yT?dbgJX4)k^2lWt33o zezr~{FMR}9%h*aWE410QNo({VhcmG<2rJ-F8go*Qt{f6?szS}z0{uY}uiN>cJYa*5 zJfTuMF(lKh1VxbB0IF5s5yK8hg0hbBvI6DD^0`^G+y;Gm>Id!R$@Phm+Kp z!KzZ^3^o?p^wC^`Ql$7s9>yfjos6~e4W-fB2xNsfJHBWyCJA7o26&TU%8bF|{)17uoSJx8mBsc9Jb0pLcpDGn_9(zSEXm&9Or{$r4==KqHIMYPBR3rmk+)u+McC`pj)j(B>LGxk=NQdN z+zvVxT39?dOAkkH@1XRipKcqB-F)(foG`g22LpBa3hBEK_)sJxkoXqn8wO-$)lk-Z zJ5mV4*mOwUPXq3L1;xllj=Tjo{f9~fy-yj4AE+^uwCGh0_CQ-1Z(-c`jqA) z9%rxbdpzL<>!9vPQcJ%=C3(jt2>QpQsl41u}-?1>CK4(IwikLiQ#&cVI9q?F4|};-qrt^`D`y z4MWCJ`Ek8Rl0%C!!*~|km_&geF&3fl5_JB;To}Qc>yt1Sz}4w^GB6hb#SsMQs}78D zp@N~7)fPUYdk>NT6OSPas49liO?u0M?&Ck-nDjyviFC@tNAtfd#XwI;2WGtFiZ^$MfI&cXxi<7kslS z%}$Y~3qXHoWt64!B#rz}KzS5gfPnwe!#Mze&i?)S`_%)#dfyY1S#Pfd*1_bU4CR%f{O7bDx<)&y?h>5eySIDa z;dA{uJ0%cq18yr)k$Vzu8~%;|4)?!W{ZD(~nl#%XfVY|Rp1OMiK%I~k|{+=GVCc{m6Ly;@zw%VzgG6;7xjJKQmE`Bhc?S95! zXP`OQ6LJac4YdLL!fe5TaC>mzh66Yd;Rp^zI)j5ZoSXNuG@gU*Dirw z!Iog>)r(*&BqL3pI^aupO-LTpK(y02uoU{O*z*E2Hx#&XU>^RSxB1n|ztaQZid-JI zRQRT!n#+EA4q?)G`2yJHX9RXYc=ukn-o<$MrZYGaSSvr~($6o%wW2 znRgoI<=^4`SKa@-2T&TUI1vimx#>D$OK1oKST9?A4Z&^*BN(rdTQ1-zg!eAiyLfwn zV-UVD!PvuCPr&6c-jGa;#eT*emXVR@%it&^FC$T|yEGi-vMUF$o#>CShvdo@?1t9=)934v7|(QvAB_L5zCxJ7SbhuB2zacAu-wBG(rFl1SblcLe#k$7 z@$G|r1z6X2eF11JfyWcrCx8ha3%Y}?z^*`xUH_oPTOWkSA9xN4^9J(>^ZM_<;jbsY z*8^~W-c;tDt$_UR&+~RgNcZ%2v4Z`!J^yW2Prr+)E!Y-h3C0>JfZnR&ptTG?cuATM z^i&oFgEghVcoPM%%uN^U3Nqi7D_FMRd>53$V?XRib_JS&odITG2TYJ}*zRuvwxNt5 zpHl;&emwwYxSYNHdp5OEo)=}8! z?+&p7dthCKaJ-=-1In>8f|4xs;OUd}pu`DUP=c8j%F}_;P?;1&@HLz_5#s=Z)Fi-6 z3uW+ym;UZN0`@K2p!r0ruMy;L7(uBaG&eASFHHiPfbDpb7G(*gtPc@n(va> z?mcSg{%4Yet&_aSWu9~0Y1kil&bFAP3*yy44yZzte4^Cm8VSnJ4Pxv*e zKYtDT)Okk8jW7FkHxJ?e9E#n+@f=tOVZDUs`t7?q3h60ilUreebo8#N0x0ntreepa z!OuhmrQabYs2n2EU800iO6ZyrYJ&TmHq?SIAfev9S3f?|2Ep!vahZl+y4 zzs3~Cb(a{Sl#${OB=W_z$WaOqz7{!3zDr_E6rdO*IVi(S4SLIRgH^wc``_aeeurQ2 zfjv}zE`?)iH4rRY9 z1Ms`R@AUIM@co(~2+}~L@lU0$^2ZMGnxe};!u*@}AX`uit>?n?FnHY#whiS_oL-)V z288wWhq%I+eu?X@e84#WR=#)tJ1N}06O!$__{03hsPfPL9cxAq?h#!jiQqq#lFiQU zuET#5W2hg0x*V1TNCvVDC3nZ`&pQ8ec<#!=cd-86J*nfAAZ&}i#~-}6AY6f~?)#ek zb9W&8A3Sgr2LFk4*ZdTiq$%*-KKx$a{#AL5x-c}JL*w|riRr&vzxW4Z0L){ey1<(d zX;#snL;Bmb{>k{qX!3$(mfs&o{|e_H-H%We_^->rk9+`_H~8Hml(;ItjqJ~reu;ls zr~x=P`0D?J_UupT-^9aAUn3Z=`(r=)OMIU}W4oUm52yf*?-I~_O!62dXd-YNymemi zyY@qdnd-l017IKUNA`b@_edq4ssG7dvM=$kinfL>|8M^G@c+Ab7-@bEW}BS(E_QqU z2d4>IqM#hq->~ofrHzJdJWST2CqZ~0(3j7^d0k${Kh*#7+5br%_WuIpdH?i#U;jRQ zeNS6>8QxF$bK3srS`ga5kN9%M_l-{- z`%_ysVl00v{;>SPe8`@l0!x2#+=AZ`iVNTWGqOKd@=wM8j?w3}y>IEvURf2iM^}}d z?oWFEE!~B2DKz_|JY5nw`9H=VmM!@AkWgI7Lihxjs4e9F@Fz>ze-{KPtX+k1OAUM%KUKL_)(iM_VD=e zGd|v5$pL)606t^#XYKy$l7Axp4VekM=PrKKZ}7PPBYeKR2kZFv{PCOT1b1cNNB+Z? zZNYiCJ=k~rJFth}5k6xApELSvwEtY=pNM}+gg01X{$t-Cp6mUU?S?Uh3AWKcip9i2 z@t`x%ToA7N^&H|`*h@pPy(f_E_>p}6JNMvsh4zP}{TbcAF8L?o|KRdPu<{%8wJ-bh zujX#BY`{3())4+FoZ$EY94oLBX9eX>d>&U|S%BMtNgRqPz_Osj!wB#5{zIGaH7t*? zFRH{!3o1ivfNqi;V7{sJAL@O{|Cf3AT_GQ^`mfRcbB%u@{&%h6{d3=sox}G|L;m*H zx(Q$Ztj_;c`vs7G!!be_M^{PqU3?!vYX@IH7j<4}_cy<`MesGui{Dp1=hx5gUBhQi z|BUWmm;4j)PqR?@Q$O$Z6P&`fcMtnLy!TRgod4R-`|{bpGoNLE+{Jj0mv5yoU-4i0 zo!{aCK6m`rX#cs!{~z&(`xEYKb0KChNn32!7t`co0Hf7}{zvn$Z{hNzvKx?n_*(D3 zmH`-lI5tpb`Q!QQ-+})lk24?~1N^_Bz4+hX!NYARhVr9+hsRY%2{y3oxBcHgs{7x( z2agYbh5w#Bz_#K?y!;*Ze-DHI*V7mc-oNz!e$S+y3E=S>9>@PD@tVE% zVV&Od3-@sTRto!(@S5}9b6=-_m;d+wI_`V?$LsL@<^1pKKK$M_yasFaTbviR#e4b+ z&kaJAPyLVOz(Iob_cp(UJzNIMNRR^Gck%x<|AV}kFaCZe{_{P&zbuD+19%;H5A(0_ zf%Vc|isQSueA(9b@~|!Wy4|m@VY!224BuT6IG<&3dKVuUr*DlFd-4Fw)c1Z(g^kEcR=hzrKdCz9`7Niz#gPzlHsm&%kn!sw4hQ8OYH8b1Vq1uf=`zoAvkj z{qGMOE&8?p>)ZH$+S&r|7=CB(?{EFT`yIF6zTpOc zr|oxw&Ux90vq5M0;By||Cisk3tfmKk|@}KKLXF^5(KvbZi5G&XKeOqdmJaoW@J%YX? z*YF!T%J4zIO$EjqoPpZc-sKUNldomq@819YPul+p<3HK?3cP3h#ab(jJ$$|s!X55c z_*)Dwy$!*aK1Se6U*kW}^D9QX-)|6w&hdXuNa*bU6%{eC5oP*2rCX|kV$k;}H?wNor$qrb&&`!Jude8O`3r49JI&wu>W z@P}m}+tv7A=f5EQVZCpFzTMd9YXUY0T7j>Et-)6zwqVOOyFb!(J5W=I0~9+6`Q=}c zILlEm(?JJp4R!dP3?z6#3D%>aI8+zD|20XlGJ@(*d#^&Bz}9eQur1TrmJ& z1ziH$puTRubs6l4^88HEUSP);R%M^2X=i$FK>E&E`#cI#$4HzF<4%AZ2)Ay;CJ~O z&wu{D|Nrkgd-I>1A=-=G|2KGm{tpY_6KIdruI-2HXd}vGR|jD%dJ+S{p5$P#H#y{A zlmg`;x^Auop5{6UN^!G*p%xc*DclPBR!iJfurDq2cS>}*2uky^fk>$CpNR!L4L$E| za1QLd8wOGMzvv#6|Bd?ZMS!2_29&}Sv0J|Sv!r2jWnc>lKVKR`p|KOTQro|BADf$4hUyS_B+w{_g|*wsTA zkCFUjh*H4Og4ECS7)l{}9DxEQ`MJRCAn3b~d-vdU_kJ3b{zgyIz?^H|pn-z)ZhiO} zX#pNkPM8lYym=KIE4=qFdJ5%XDopK-6$A2GmuM0mtC--^%vV$+8^qkMt0_eh3;U$wJukf@g&J!T+zl?|`c+N!E9E z-+yP{=6$>Sb~aAfo%m*EC!2E|6;vdfbHJR_m=(o@V?tES2}KbFL85?w89^|oF{d$S zJ@x;-KDV!jDy7;;cY98jE-haba@w0a$@J3&h*P$p7%_ z`LcJ>MAthU3Rs89);=r70DBhCgV)~}HVAQ^Fhlm$UjwbWM%7LFN;xJUPXyDM<)Sb817Z97Q{@KQu_qM>h0tDw91*ADQS=`HzoR%LRY+ zL#uzvz?p-4WNw?fl0KxBA)_z><9;U%jE}P58^CvXs=whz!ik^1AfDD zC~xdTI1iva#tmp83%fM9IJaBVzW~*zuJ>AEe#rGt8Q_?3?b!Yj*{``;YvX*7eZe`j z)0g(;$d$wUS$%U_MXPo=Gc zUT#r(&HBH7>X_U(eL`-WIVCsF+Th$Nxq0^VeK>bUZrTCyI*c^@?)s?{N=~jE-lzH# zjxD(s!1c$J5q>hKRc)Emx~wegUWRCeYCU~cKFiQ^?;pbWpG+;tE$Lhq>qO;ce%soT z?%x4&V9pOYCp^0?RoGXvJ)oYm9w`H=?o}P1MO|9~a=<#LoIqx%^H+}SN57J-#+95y za@~n*&*>vO%Ca7f&<+id*zs*;S+_FkK0e^-tp9>4>lwsT56JsP9m~jyZ~SC=S070m zjQ?qx*hhBH86yW*%*0wwn3|ta9?tLFtj2s7_hzFH&rxFqju+UUGmhgyreRt&r^DJ0 z^I%@glX-`A^_3L^{p8$t2Ngw$lRMb&VszI3GpOW3vefM$eY#^g+a(NjGq0_igm?3i z^_Yim!@e- zTbc8W!*SvsyJXihK;H#7|JQt{|DxQB9RE4%|9*ettpDfB0j+y4gA6+L z|M}KEOLNx0$#ZA>|Kk6Hz^VUE{eS)(aOywx&e{Jv*Z*IX?&&dzv;BYmHK2L#)PJY` zKY!^nOVl#x)c@yS1Df|v{eN-#uj|0+-(LrOk-UHwI`@AuCwP%{@FL58-u3@9?%rnm z{Wzfc{4(G`Tpovpr|}Kx*SvV%^-ug?l+!f73^)*%7v)I5<^^zguI>NJ!26d02WS01 zf9cmU@2r2P{y%@|GfUJm=+yt`Ujv%=PW^Z4|MQnVr~Xs_UIyKJ8E|m6|Ic3oo$bHL zbIQNw1!A1@zvn25n(t2ie~wJI6{UIaZ2z75|NN!TEK$qg4^{tPhO;-%;{M;Fp3AY; ze^I}A+UZya8V^Y2bM60ixlaG(*mHE&|I1MiFG?Sr_3y0zXLawB&X+RwqU76IZsGFn z)c?Zy^Pet1&iZ%Oziy|WmG5l-UtSq=>i^4IH_xN*an`@H{-0I5uk&@b|1YnMIrabL zts7_i|HG~uXZ<_t|5?j`v;F^J%b2tNo%OHB>Ceh{j{jd?8FT9Y%Ud_ky6pvfJS2lxWTXFd2zE? zvDd8;hl>?^)%rZRSTXAd25B91Kfzr-m%smfkfNo05x>4>kRDA3NP~|et#{6Kfmhm-tqaz4(}iJ`4xxn|I?lyl^>4j z9r^9}{IL3a-GRT3&*dH74|>S6IJ|dwhWzG{C&+i6XUKn^XXuCX*{+PLy>Rlw$qzdR zil865fp_}(a^OAi@)JN)z$?Yxz;Cf)gWp!(OZ79X>PNqs=<=CsaQ(0Pg?N?-4Dl=( z$S~tZR{!`nFBP&DWWII%{ImJKWkRFcRKKyIyPIt6?J1l3coPhUH*~9KM7FMeV*%1k zs`L40mQP=3a76WwehMB>O6pqgZuW@Q#@-2CjDwSU8Hc9yu|aP<_cZneb~APb_!*gl zn;Hq7T<`LmfSUjM>5D{uY|T%8x6rptI(fWzd>1+JZ4cQ$v4^ogu$$zL?JOIHw3cln z+ZnsZc9h*?Iud`$9o1g4hPO1*dej$w8|d=s?_LBA-?64_>EFP}@oy(P{oBe; z)WO2Gb*08fZ%Mg#|0d<$`I}J_;kFe%F~)mUlGtt@vUNa1BfY1)tnW}$(J;2wC(pee zW_pyEgz^nSN@o|!xUspPkCE2P%c%DL-;FZ=_%q;7Mrp!Zgx3_5f#1C3dq!CE%IaHw zAA-CJssrQRJ&#-0FE0gz+Q1rSoPO56H7?)qfsKi=>)KW~k~`KC!un3Nm7fBConK9< z`1YTq)Ej>U{I8UL)AUPeA8`!Vc<(O~-~MaXff3WD+TF2nQaVguKWm?H zHvAd1zt`ad8QP#vLAR1U$Pazy z2^n&A)C1zb>M7#CJ#4mFF3OC9{FZ;qloR4t7IHnN&R6PvXp@Rk`-8vbp~3b4{x0j< z)lhto0si2ZwJB)kEqTX>$hTn|{r} zW}0sjf;fnu!O$Jr}G*3F6W`-B) z%+i*QasATH{{rM^DdqoBTw(3cfs8~W3Aj>D>;U|!kL7G_CUt?~Wz8x}{g2;}n(zNj zhS&PSp56^{{wQJ1Dk=V>&WtGq=i*7$P|LIfqRU2dDZLdln%Sgz* z<~92<_6y1A<7PJ~FRmZHj<)N4){){r+fR&zo_YJpb~HI~fWjlCYh6j}<0I+)d?mGy zuT=l=O)2yCU!}r(f0vX#4P=B{IVtnb-=s9+=r3(wPc{y0DjNqilhGIph2lB2yPLv) zK_UIus&8r}8Z5-LUuE6w1cVrmr&~|1FXe>J>_Li(E0~ECRx~zDX`%(rr zbd~IBgT%MuS5o2QcNO@#R+635hX97k&fuYv6Ff|%0X+uVrMpw=ev$8-z#Ko6Hu(Rq zHn4^nr=PVi%et2}&}QYA-kxS*tMcGubJ?>nP!6n^DF;^0l7TIKB{wuk4u*#SX3L~r zep0Q(XEFfsd%|YQp@_LAtez)_0Q;6sl}$rh8neAh6*zu-+Wjx(hwk>xn@0So?y_sn z7&(?0AtzFzRLIO8m(Z{^10HpRTDXug1EGG7Kl~pch4U$%iGjWpX64&!0|Ki zf2!jjYdd!R@2>a5;HPQQLyXM^9cjLl2O z7zvoaNBg%o)(&YY1cnnP_fqdP9>j^bIpXX1Od418sch_unK3( zN932@p2qT>q|NDX;2WLZnrDGw;#5TbKh^O+<%LemKf{zC>;Ds3-xU;o6!~G=M{$LX zfAY)6hJSvq3XHSiUnKcqTJnjG8JZ#US3hf?v4zdQ^taaZ&zS$As|M7htceY*VaDla z?Mqx>E920n$o$gV(^$Tf-3bc~e52D_^DHoI!>LH^57!eohStFP(7-r`wa@Uf9_5Uc z{i@s3IHuLl+F#kXD%UF>NUz`1x8~0qS?l`)~ zX+Lf9QzZEh>s8U%5*i>ju!b3@pS3R$gItW{;O_aQx2LguCy7%!7!iY9b$V-_1%`=J zQRP3hOG(3iFOoHkyNvAbtnmeems;YjVS66T&zdK~1*St@MZ|xp%AaMwWKh)hGY@|( zJj}x@Yy6Xh9r#~h*(jrk{0}WK4{KRZg0uBoYn~4Y7ZLw|Yx%i$;dCh10|8tYlt@e1 z7N_57U#%bN^za`wzR2GbH^=#k<1@yKCDC3lg|F^1vxXU`pS5p|dz|nie&f8y%dx_o z&rS|FIq{@k~6BE?3>U{V230*BiqQfflVaFuXZ}qJPRB^W2=L%hTkSK6gKY=XI`RR+RX%B2XTf@Lfw0!!n{&K8 z?^9;>lE^M~?0dM}LrjG2i~GOcwC|~Fn+5uQWz=4wKrWK3@__QYvh2bf_nj{s+nXoJ z(e3H>z51!{rKDBKcVYWcM#f?f*;+2c+`H^kt|(RC z{fjEIS@Cz2O++n=-Gl3gf0vQi`?c=1QZJsg{B0p)RG!?YWqHlMdRx}oY(hetR8sVI zE&rhqKc?wa?gNQxT}^#M-L#hfIQ1Xh$5Z9C1o>;)=3`%Yu5UT}Gvm2OP9Crx`c?T? zzU4no{cHZ~vS}Ak;h%p}c1zP>AJeP*M>K*{DA&FPW_W-@qryAZCGnLyk@@a3JZ~y z;KWmA68kT{ymZWVJrnZzR2>)e~zsw!_N|I<9FwJ zB^mw_I2;(op}501NScJhrGsBd0#5nC;rsDS^W&ldzWXsjr)QWAkak?Bcn!cwxn8Ge z`rmkXimrXhw~H@mP;ScV*42{<3lZ*E`kmtW6@m5pw}IPR@INIW{F!4|$6Yvo?u!+j zJ(g#WXk+Z3*xkq--__VNzNIKxxnoxe(h;_n#&Ze@&w4z&d5z=CvMz|)<5Kz8Kx2Ow)rP@cHB;K7)ut8*vn zyho5{Y0QuFo{{K}c^c9f-O9eFcm=u}BX4DQgR+!EoU+B?-u0EUN9}ew8MDT!IZns2 zA4nPG8{$(=X!oz@DsZ-O%(YcQu} z8Es3wCp{{DB$KfgFtXO?Du2v#lXd<(A|~hIgXUGrjGnS}`B?kA=pLS!M^}^Z7FE=l zm?1Sjl~oAqd1hnVxf0HMb^c&Q*P`OTF$DZk=Y?uxUjC7?ukKg%6LqFwG|m{z1TCD; z<7|bosKKN2=g`jW#`>=HWXs6*GO?+Pc$E4?X0>ydvhTksqZ+%&_Oab$?SNL2+_j$3 zv;6z2e#!r$@`rqj8QxY7gayl{MbqUl=5`z5`*&$8-^DIhc8|3Ejp*jRSj(r4KNOh< z9OOqRKUR15?j6~>c$yrC9qy$AyXDfMy>b~glb7M2NQ;$}sRQNwnbT}SlzSBUQNoKK z^hd_V6~U6Va-Qs13O^JOK2N^em2HqlB(a}v1#Vp*g+Kg$^AdldY%%Nz%nL40{!Ejf z%a1=y$NrS>@^iMl?D;<~f0)1K7t7IM=5OT>^9N0eZ+J)F9tIB#n||5j_#XT*Z2ZZS zp6|#XYyK#j`jsE4iU*GJ!-Ovze=@_rHDbp#7XW>Gc+If-M)c^0I$rxYC*y12o&DMR zE%G9N{-))h{DEEWQyaH4FF5;o0@g3>e(m-iU2OI^^sQme8+4pC-XYBVk>~pwe}qe% z*}u)$le9zt^a~1G-xrj|KwixMuR8yKXJ3q0F)n+hnB07&*kBNnKk(h70qU1)Z^hV% za(n0vfF6fc$Y_1}#o-(haFy|Oiwn-AsdeztI6p;P^!J68zhUmT zILFjLx>PSN-_$K972khDlKMB5#WSAA`;Eve z9grp)Hf)fTlvGJdOq8XayzIEDIRnP}Y284F?LLq6US6Q_Ey4W;fIry*cN|D*oEgPE z2PVAvnpDUBQGM*EhT?3do`2BCS^G`cL;Zgbp`EYo^k2JnLvGx-sc64;?Yi8(dr#J` zT`PO`?2)~D_sW3-2jtM9LvsB1aoM_cEBeoSa_`<QBjhcn=89^?NWT$w{M>uIdVkF1!aW%x^d&W&1d+g;sND? zVdiu7>NN%DPoI{^9u4d`YP$3DN4b2d&N=HoswlqW9&%`-^0|WFxo z^=~NpckRlR-Me=y8Q8!7fPDAeQB}XUZ{LQFP*3gydBS?9Zm`a8+%RS8+O=zvzA#9g zJ9ng)bLY{ZmwWVj|Cwpppsy_o-8zllzt{QmjQg~DUp`C*?DP}&q@*NO&$=F$E?p|I zv9W+SiHnPu`1k~sCNeUr0R7*nc(Z!-8ugxSNm^REg5`ZNrv_bC;GF^7111f$LEt%X z?#DCDw{9iw-wlHInodWb-!TvFAzSlic%Dz`h@#d%X(s(?X=$oXsn=`QMx);M$-aI2 zq5lWv(4oU};>1blKgZ9aWc}`41G-{xJgq?MKYhlrO}KIOibQqw$b%o(PrioUI?~hl z%YUkL%bQiQ+f6v8;WPL0Jun92zPi5a!jXRT1>ZpjeqIO$iuUW*smGN6 zwb1`v(Er_#i@k~uM~-}#NB{ZF&6{SML7z<^`vB^NDgQU*z_xV39WHt3r|pF!U9<`4 zRPO&&I?69?WffhKuT6JHCS?`-RZ9=<$TeT;*Zrzm3HA^07_j$*Gm9A>Ak>UCrZGLK z9}E4DlY|6Q|Jg5)M%J?_&_54uq>J}I&@PB~0lEL{4Oxo& zP&D58`KzJd3mTTU+whRy23RYtgu6y44{QUp{fhN_w1LBmLO*He_=o*Hc|g5o|Ifak z^?vZ+K{kNH5NB!Tv`a$`(;;6%H z``Pcc$GsV}SJLqX`Sm`2J&z9YZWOB=J&yd7E=`A~pEAL*566J__5Xgq&u{MBxr09c zwxXZ9arZ9AeYX`H+P?9D_RojoA2uYfmvFzlwvZY}?NgUE9olDKNSis* z#rBc%J+WR1JALGfRR@@d&X4}1^nYyg^q5Z9e{^)Ts&_~I-@bjjs^@}!wEpY&)TM+m zz4G8@#gk#S@tSV>tbeYpbYVZqI<`SI^aD%KZt$KN!a%ISkU! zs=cE;7pDKDPxFdttw5To|N1@UiLi0;^!wvq;7yy{l+Lb_0vlOE-I)z5$%Y>8CiL`>kj7QS<)b$x75h4hFW~2+j(VieCPPmenPq0DnkLwp(L_=oz>@&CGY>y)p@0PNpc$GU%~zi}gBlbRb-|G7>; zKA2#R6IKNdRrQkA+e49Vhvd#0X+ns<>D#yL1yqf(O z+kaj6x((3tf34g3`CK!}&)q{G5rw_Qblh8-jXk=3p;Og9;ei!1Wc{>J(y&GaIf%Q0 zG-NNFB5mDjic8tzQm0%A3GCL|es>V}5DAA?%~5b5YzFQ;8j8Gq1oxyq^7;qqXWdf| zI2WR0J?G@)s5JmR2H^bP)bBesz2`R^>zY2l>ka-4v;!;uS>9dAUt z+J`39`|9&T#(dUS_W2KKNJ&Xi?LEVEt5>g9v~vx_k$$d^+`4sFt?zJ+hy6X<1Um9Z zKQqn>d>=D!x+D*6Bm0(2R`(>G-js;Deb!qbS>5$R+t{tELuKmlZP#FLTbUf%?8`)hfjU@?q1ayuh_Hwh!wT1WVkI_K^P>pdl6aFJDT(tIRNKBl&I ztjFDbk==bHv8R`8#Myz&@jVqV%(yjpmo#C3Y+N!!E}l2{=0F_n21(1KIy?QWyVTTF z)&5Zr=;qI#uhu~C>wmNw2ZV=*E8R~`-Jr%xY%>UK1IQb`r;Kp@-y9pT4KT+7TK~DX z!102PH`@tw{IEKFrNo6TlE@hoC1S!*1(7oXRou$u%hcG!lvA^x2GLJUKl?q7Z^#4P zjz>g9sCJ+F&;DQQKgTwOIr5+|r}e*}G=;tA*qgG&wKhFZc^dTV_K&o43`D2ppJM<= z{kQh*j{O_ufa@pLcpYZGtaEGsXpRrewnV?zan`v7<4oNn{pPv@(?2cx$pc*;^IZu! z&fb|LIamYS1sT`_{XY!-&rteLz32Xqx$mQWem8qI#%1U$wEk<_`AkRov9=HTJ$?ON z^N09oUh_TaH|ziD)33`RZ;9!yrDNqx;(R%iv{25jUnJ*Km&&D#6_OM-SJt2pr+zpB z=ghr&^^!Sr=GgV$+6HL-&pSUb+X2#Mea~krP;MxbbWgkfNjuvx>N&$o1J;cdbTDYp z=ZUNj65(^?a0u`sg+oCGn_29~}T>mWgb@ z_IlD(fw2|nA0hYB=E)uG4`{h1zjT;%ao%8+Z>-T)tJkhlC`B~C$ZT}Sg%X?rGWTZ&MV3F_vB4ND+m*&g8b>rn;cC_5v5h-^8 z^fgHCI!RhK8#K~p;J&>8<(BK_Sy@?XF2OZ4J~Q45nVFgDz4aaYJOa~kOiuT#>R-zn z%h-^Pc`SU6hBc^>(Q=#>0-cf*EwXd%eaJ=_@uw5!OHS@C``nr1N6sS%97A$Vh5f0H zv-*X-=QnI$pGEsmy4i2*_K)-Lz)D!5& z>BI%HGbc9>{luL>`Z&(wm`cZ4{leb!8@8>_f_{$s+5T}2lzK)-esG>*2ewCiF}Jly z{I_TiCIVm!YK6E-az16L?8d$k@#VT9Y1+Tv+(+gf68F)#mq1=SLSgUu4ROTIlA5DZ zU+JF4_=oG?x}DMaE?Trm^#|+|2<#u%Z^YhLNE4AI-2h!Jz~}BFOL4cvib)cMy>rSc zfjCp<38a1b^5ynt9k2bu-cxQCFJ7!@CcXr^r$s;WBkcsXF9kVkTR?fxK&de$r=Tw% zKb|sApwl=$P5No`a`UFS|I76c4djCv&vkyYAJ%fBeYOp{uhPD?|6-i=*=$S9^@7{C zxjta_^Yr!nn|bSUZ{)EtV*Qx5O2nD&Y1F^KZeh#DE%F^~JfL1M-U1*l4=~;eczkNk znlHnSWfLC_TF_Ku^yKvWX9vpH5nj@5W*?cfGDvDh_=;;p6R8`~RO&@E7q>Mnr2d*# z;vU&r>PNN}kEpid8P#6A*7^ZDicfTBKo{|i?kWvpx=TYqqjkNc@w(p9IJS>8iR}yM zFU{fx0KSpt@dKrK+#qR@Fhp7=43$<1!=-h?2pf!q|1dDqwu&DvfxAPWxc(>XnkF8R z&BSwUbI{X5eAc$ca|_VlNb0NxA6A18tHFoWomYXw?6O0(E*(jvB}w212^E#rDi ztN1?BI=-K@N$4+a69xdjk#>oLq5%0BarRlmZ(rjH`3(haauu``Y=@ zM)6}H_%Tr0CkzHpz>h?eA05Gujy8UDB0tuHAM3|}7ld(gpC8~!3VC3HqJRIB(?5R4 zM5({hTk3>+ipwewskWl7qW8eXLvrRCXeTHhoR>4;$H7ZSz=QKjHX6nFN#mFfko8W| zWL;-z8f)W6Z1+6;Xa)IrkROnb1n>j$VdY1Mq~VGm9g{|y@<8qtIqVwM4stc42KB2Yz$_PdY+II!RN- z4^uvxIq;)pEZPt7q&4`_2K;CPezalxLHS5P8-lj7J@m!o2jm0%=#V&4rtV$##PmHl{92=NZ8E`>WcS*dg8UnO}rPoD}LBz zV^K}b(F0{Bru%1!=K&RjXIbfe~+YT~&BvJvVj9*_->FmLgou8M@$#!4f)Ysf$DF;j~37uLg4P%PfY*h zm_gz-rnCet4U~+`RH-%kGueG&r`)`CL+S*U5|@dk<>u|{a`wt8Idl1x96WbG&Rsog z%E$bAkPkN{A6`q`#dE2tD;~@8^243-0e+bJ(ggZq_O*&17;C8ZBdWD(Kgf@UHu-3X zF;*jtH8ek(*!cnZi0LL{cg=ia`lmz=5O4ny(kGyUOkeP=)E@dF=)Ea>j%SP8*plKp zwz%B5eM8QIb_Hk`V{_JsTToT;34y-Mb`|fr1nNp%@mffJ)E6)4OCEl#@D_K-hdboM z-6kL8hdcB|>C76)2igxW@PqQ$ae20D^KErV)ZA1yFGw3668~UmE2H?Eh*s|g>;xlm>30tdCpG)n4FU2jetaweX zBHq)gskXy=dJXZKQB%BTq8(*hIvZ!p!4r>pb;JWa@mN?-+|h=(FR3r?OWmdZG7qW0 z+*91byu@v#m(&aQ!C2cD&_LYKj?~8(%pGG-_ccwy8;niYfG-$_dquWH8{0;F0N&6Y z|LjSm|4YE*?En1)-~A(P=Sm4#JxD?#he$}&PzhNJh#n@hVus7Cb%59rGAnMR%!>Dy znF*t1W+DK6@67c9G6Q3h87X5VICZQ9Zx|=RX@GQ$OEV@&&_=+fKndCsDATu2k|4si z$r6+~S*8)PrpUDHsWNTnG?|tI$PJdMy8yd`Wy+qJGF8DWnYI_3io%%=skJ{|^9Zc~tkKpa0_L|AUX-1n|t%7yo8JoZqz3@FRpD$MHL!m3kHM z(|g#4rgSbl3FD+x*vU{;zHRt2Y0~4*n~) zXGg!7E&g$R$NcoOWBD2{ji<(2)A57#b-g;S$?*(7?@?+B&}aAu+i(9sWWkQ@3fshA zSb%2=t?(;66L4F09^kbBR$v;oSGaxqK{u@GN58?jUDx3HU-b*|ED?zRe-C7saU-jL z%zPfzz4Fta{*-rMcma5?Tz4Dvgiq)N=wpMv@Of5n0N@+IKpPB#Kg0%1`g=QKhrlhbaxZ{Pr2a#;tBlEa@o+Wo)Ou)`VHL26gsJZ|M1p%IrzL2 z`zyz~e4Jl`6&mMEv@zzyI#{;PIrSuJ!KXP6Y$^VH*eWzkY|N^szy2 zJohyA1$N{A+8ddJn;Hq7T<`LmfSUiJOgzjH|MJ9_>(p1TnsEL44ZA(9x$kA}gK@8j z&pdCIo4X5kcRAQA&6do}9oYBWrfg=g2V*2Br^w>Db52dIU*Z6Hymx#TIq+={**~#| zu|Kez{wvp|O-D5kdJGX$pIPu%(4`Sah)nKNf`cIKGu1Wloxy>Wi6 zrflioz{v4$Cp&Qm_)gTp!nSp##z${SIh=DZhdaG$BHXsZC&qZMN)p@6L$(fRXr%Xa zSO3|JyRp*8*7~HdddP!6aUyWPf%wy|k^JWV9PQM&@4)wFJzbM4SFXtR?U{1<@)bFI z_N<&bbxNK6i5mBf?LVVysq+hvabt5oA0w@omr?EgzZ*EW4)~K%n(!9kH3enhH!t~~ z5!Sr2{r{vxJW5O|M2PJ8b1!E7`ed9xJEHa?SFesxXVvtc9QW5q3-_5>FQhFyd#9q4 z`|VnO;#Mrpb3SZ+N1P$SS%DOs$H4#X8a#_v>J9sOB7^5pO1|;G%GY83FMK@Cp7DM% zoG-eI^MxFP=I8AAlee>G&BDHKJobU^Nn&E6!j-(=zyAQ_hc->vN3-n(F+FLf{L{a9 z@sgZ7cV5WOmipCRTM$Th91s(acXPX_;gxxDQ^rt$yLCjK^G;cp8s$9)0BpS0ty zfCuh8wh?2;pE69GxF3~Qe#~>BwD)8@ab;SqE0llg4(0#op+mBU_ge#h{#Q58dVAx} zYjxHK=hkL=nRmY7|LYCnUJ!u)2LDr?_!IcQ(&KA=l3)Lj2mfo=DF4^hJ{@hgC{Jul zXu}y3vrg5ADL2`Q@06SP_;}f|V+U+6wo3H;8R}dGaVOu}mCk!U-3Rx$Fuo=J^WDm8 zT@Rp(XWR{aR++dnJs zUZ~6I3#Tdk$bX)lEN?kiToz}m#^7Fj;uDHaeC=e)vs( z|Emsq?D!LR+7ww{l7cWXu&`3M}JS#{Z6MP^; z{BLr79$51fXJrk4+^-Yh@+JTOTBf*{luG~nlhTP+s3X$Cw1oWr*WQXhc^VP|8*Rt~ z`%>EAkREOG%e{N{1-kuV8$@6|u?}d{6A{qYF8e_qrG)no&Gs!P`oH4otFY1!Q%AIn z)AuX=ejc5eD9;?Sl-+f?x#(`lc$Gt9ckz#V?%m1FzE zxN(pjo;|Jj&(~y-?GAmNPRlvZvs&9y+<|20|HI@*%LMoRDdX1uSIZCM&Aoc_3=`85 zf5uV%vlF5${H6Sw|2+_m`$l*cTgwx}%W#)SeVk9{eGJ2EexYQYbkzIkbyWwrx6%k} zR!Q+6`fE&ii2f3Pb3Y$;rNEQz59NpFZ74(RzgQnyZiqL5=aK2N4ce5p0e4xN?WdMo zp7o>bE8KZL68gY1u_Gb(>bxYLc|Ml?0@Fg?4A&1|*LMdf{O2g+~g`|E1xaR(d~QNyT}!>L0!-WpKw&h4=n0DSaBK`+v&3 z^EWAtIQmO*#})p^o?wi|SSS?FsomWa{tJrGf3XeJ`b!%UNBQCShxn4tTer0Q+yw7) zRQt*LV?TB%Yb(bI>OU2BOzbULQwAt#{dHOKEcc}hY~Ui<(*}u8#jkK)?_CA$T`Sqn z_zjhvIG>giJj_5EgS4Psx;v%r7Y`jj=y4l$lXy~oC>sQx+2{EL@|vP+3FUVc)oa`g>2=K4oWTD?Hh5k_I}Cq3_-`?+h{J zXP1iC?Gfwe+Lg<)W?(znHD`<*ON>zG$Bw5&$%)jp_Wx7gw0y4gXw^iHr64YCodsf5 z`rY%#%knn0(0zwNvd&TQel*7egTO*nO2u6%b;oz>ehd#r2^npK z^EE!_{uKqI~D~>7W}wL17*SD zB|>{!)(vHfXXpY017+B-VM=~b|D7p~&E-^MOF-!JD~$)%MNq?!uFlGli!Yf*8DCgp1dRfAGiJCccg*iAnFy* z^|CDTi+LXk87NoBc>%oTT3`dYHo1vh3u-AhX0(;n(X`uNr{)Yy%kMaDV%y8G6$*-H zKlmj0vkf=bugo=Eb3DVohqYmvMN^Kb+ZwcqG~XBIm>d9Gd~NM9qV?YbRp&PiWEa1ZY^Sie^X)9?}f+eiQ~ZV@myy~zR}t^XRh zd6d+KP0BpnuaS)Z&~S~QtzRqHf46}xS6kQsw};(h2iQY*g57r)X#|_3#<10DysoD- zh0SX-*nc;N4POh`sFh83}t+FW7*( z&8sc-=GTV3qr22zSWDqwYboqsVYfwFwpuIQRUGLtZ5*{dFzuuB+IlM6S7jHS*XC8( zcE+3Z(B8FOJn9E^r0stFK+p7D%O6R8{GQ?uK#(r%MBd9drX+c$$A+9uK#&tki3){kkk+8k#hXwPigtHQoJ z&a`Ky?e5fEWv^Rg{*Q|2Dc-P49Thl27Oz|&9@DCbFKkk)1j0^lP91TbQAJ#5Rg=oW zWflIl=fn0+*($>pmG*|p))01=u&48gBt1=)jiER6-Us%lJnO;sfcEPRX`2kYLM3ms zvs85iJAT^X;w(!`v}KcW=06hu1H!sW!!hN>cU)QVnNUs|Ospbx$CgmIRvDdl+Es7r68Pk>&?J(_(Z8nqM%4U-G=b#7eGHoRrqCHc# zqtGAPjW&TDZD4lDqu^g|%wpJ{4lgN@~fGAeb1j7l3RqtgAwKVy{mZwe6q&0}QbR=~D#;=g@7V1kU=9w?(TCrUu(B*0_| z|1O&Ne++mS{>6Uz%U}G~mX`FEe+htieEiE_{gQYU)zOBAw7x7*psnCV$ki*Tox}X= zwL!`+R_t|~59=PpE6bNWKB!X9+J|+IdVXAA=cD~s9m>^s{0I2px8m<+n3~_jJGe-S23J^%bCOAy5YIG%#H$!0W&L?QfMF@W0mif7ATWYyR&yfnmn+ z9nu!&imQhF5q@soyal_G?dSjShd;EM=2rakb$+fHJBBuuoKfv$-vpeUp3p^dMz)b{ z1Di;UU+r|q|D$(6rW}jDdeyvR-&`Xw=Xsp#u`F$qa1k~Xr%#_z_7<>LFmj{AB(ZDV z>-z$`quj2NHQG-mHLWSro4ZKHpcaw~n;ibvOk!u(3*bj9hjR6!DxbDJoF{Spl5=gn zH^VUJjNBjQIq)@WR%5L(RHly|DY2b!?#qadFM9o8rOTER-gZk&UBEAJpT)BV}L6E`|mHP`6FpPfBrmdg-+w1=u^sOh&;G{ z{f1n)a8dDpOLVw>uby}Qx58cC+|M72J!EUS40G>N-|O%Azv$NTX>X$WPg?=f&bmHx z=CrB{&b>K@CJvi$4=d^6UCa8u;bz6(Q8p30M^@v&|7mypPX+3Qu6S$t7cQ9eb3K9U zlw7ypwvGQAvRSPYaQ&KlDO?{|InYm)&wW~!*X*me?e`kF1gp=kJ#;U6Kuxhp6)T|Ae~!dB^Zv*dpj>`s6oxKz{VY z|2;CUpz=@Szb&|iKv`q`^O^Qy1lB*-UMPR$)21cCdCH+(0PioS-O@CV($c%~$HM5JbNXu%a)Louglln=*h|aPJ`?cZCE9a|!q-*5J5o&FfwvPbJ9ee)Sw2(FXKl2> zCONq+O^$C)k?(hI0c=&Uf7M(WTI-8Z`IK!h->iQ_;!?41dhNEHyl`Dke1A<&UA!*w zX*q@o}QlSjk*4JPp#c^9iNVS!jvt# z!pi6SlP6EAWj&c(7x(|H71^=U1creVQDYmR_X%_v?(XKAf!S}H>&cW8wpZMf)9D^o zKI@2~^AF2P1W%hyYd+Gq0Wb+La?faBfI#Dnf(<+H6(T$_UWp8_6`50kN;0NxvO znk!%7#`>`X>Sdm+S1 zVr{I-3U`19z+0+^V@(eCmw4j5s1Mer8({6D5!P`U;p}iztm8DrdUOlS?OS5)vo-D! zX@fgQ+9dc}fOn9LkU=|U6-s}%jNZ~Vypw#rs=l1Mc1mvC#h&q9wDosx;`t2Ln_J@C zGVaH~dH$ly3VXh;a_dIk<;hh)eT_0m|7ZqB5ulTOwfpwJ{3%{1@ zcdkk4g_Y!MtfiJ&S_9A5r54s!8$`Fk+7{O9aITtbk6f$M_^3Mvc;5ilxXrst%sU3S z4%`vYO|8h2R|sIO~u54~Ax`^S$LEgZa5~VN8spX~o#4m7W`MT7cUDZ5;%=76ydyKUv^S%NbKByn_&IWTmvkC69G1oGA-n^H5 zlR2SK`uorJmab#H#ckLp=;!ZB)j{toK3u(Z75(rrah;6w^teyJYmTdUVjavAXMjDh zrss||z50;T`nXr3KGs`#2HIT91COvD!86ZX!|SzmWMSoh6%yV@h6Ve|kXa3-Z%}<1 zG_Q&D2=R~}b3CQzf(9~hc^erR?kC?wbdUj&on*k;E;0bR&_Axb^h@k1eUp1j-_$3OTLw$ttwW{Xw&61IpgLck?|;Jo>es*ExhUH2m3)Tq*)Mv!DF|`P2i{F9hn~-Roce^?&{gw&6k9Bib1ICw4b-$9FaMjPI(> z32htH#6USgrCh z|5)NbD~$lRGDbp&T7t7+LBPf8e0Ba@x1dcD=aBR{hvdA1c0SuTV0{7W0kB0@XFh`P z-&dvI%=_PP{V`WV8lzj;_pH29`IjqKUKK;TCeB%Sm;13}$J9BW&6~H%oSrS!Jf{QZ zU9fScjk@9T!QbrXNN~o%nB!xf)4=(oDHa0k`0IH%=UyjHoKpW6NqY;ydvhTksqZ-vVwvX*0%Fy?m~;rn-KE8oT9e<)z@ z$p6#`ZCN8<`PBST^P4?!m}5kW(4Xq2#=o@B<2uwhzs7PL_LG-zzyBr7pDyFB{>$)B zq{SLBLpw}|y|<%&+2u#gI5>ZD$e)%6S1`!tIJ=swn;gl_k}XST$~MeZ6Q}u0cKAH` z>dn`9ZZkiZH-88I7_(a_8e|IgU_pz_Zz!RwV{rfVDp|QI!hYu}GWN|cbH*I~hP$i%ZXesddFEYU982Ne8s787 zJJB%yZHKW%VfZ)4*!|Pu|HAmlMf_H@lqw+=aPQh#slE_<)EFn3_iyn&A=;mC?AF|N z=axBEYLVK#(EMA3)Rcz7)x>2&Nrkt^^yi!BPO( zM#*gp%ip^L_SjoZt}LylRuP|XOG&dCINygcaq~GY(tLg$X@>h>n&Ix3rlIcAWVwel z#(i_-Y2(NS;8i1OmeP{>djlSDKl-m%eve2OK;0(*mmmG)N6hEBIWb->mV^lPQBOH*s%qj83cxHx`4WyWmS%{CC3?q$NlX41N937lnWAYG~#mv8Ep zlZx-ZAxZt4%3_>T3aVcs5B@CQn1*$?T`?vEdCK8qCnas#aM>FZCVSVdl=%6`LqlCS z!cE+k*OgBLKbPug+pA$-?HYmh8110T+LlrmbLx6%bG>lCoDb&uO_RIJZ(sXyNBj3b zE!Nm;&exKA8s{-jY?m#^H;e0H*e|I$DD6pTAJY^z7rcwCwKPra%u6I^#AUE|BGS`n~p0j z2hZ#hk8#B%7dZF?Rgor`7dJ*8jj)E%5P38JKE9X}H;Qd0zyHfm{B-$$t@+BExMhRm tj|RAXqk-~&4*zF>|F*$T;S*j3{G^!AAFC95m){S51wcPP;Jb&w{|Ad45fA_X literal 0 HcmV?d00001 diff --git a/applications/spready/spready.lpi b/applications/spready/spready.lpi new file mode 100644 index 000000000..4f0c99328 --- /dev/null +++ b/applications/spready/spready.lpi @@ -0,0 +1,191 @@ + + + + + + + + + + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <Icon Value="0"/> + </General> + <i18n> + <EnableI18N LFM="False"/> + </i18n> + <VersionInfo> + <UseVersionInfo Value="True"/> + <AutoIncrementBuild Value="True"/> + <MajorVersionNr Value="1"/> + <MinorVersionNr Value="7"/> + <BuildNr Value="2"/> + <StringTable InternalName="Spready" ProductName="Spready" ProductVersion="0.0.0.0"/> + </VersionInfo> + <BuildModes Count="2"> + <Item1 Name="Debug" Default="True"/> + <Item2 Name="Release"> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + </SearchPaths> + <CodeGeneration> + <SmartLinkUnit Value="True"/> + </CodeGeneration> + <Linking> + <Debugging> + <StripSymbols Value="True"/> + </Debugging> + <LinkSmart Value="True"/> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + </CompilerOptions> + </Item2> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + </local> + </RunParams> + <RequiredPackages Count="4"> + <Item1> + <PackageName Value="TurboPowerIPro"/> + </Item1> + <Item2> + <PackageName Value="lazmrumenu"/> + </Item2> + <Item3> + <PackageName Value="laz_fpspreadsheet_visual"/> + </Item3> + <Item4> + <PackageName Value="LCL"/> + </Item4> + </RequiredPackages> + <Units Count="14"> + <Unit0> + <Filename Value="spready.lpr"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="smain.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="MainForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + </Unit1> + <Unit2> + <Filename Value="scsvparamsform.pas"/> + <IsPartOfProject Value="True"/> + <HasResources Value="True"/> + </Unit2> + <Unit3> + <Filename Value="sctrls.pas"/> + <IsPartOfProject Value="True"/> + </Unit3> + <Unit4> + <Filename Value="scurrencyform.pas"/> + <IsPartOfProject Value="True"/> + <HasResources Value="True"/> + </Unit4> + <Unit5> + <Filename Value="sformatsettingsform.pas"/> + <IsPartOfProject Value="True"/> + <HasResources Value="True"/> + </Unit5> + <Unit6> + <Filename Value="shyperlinkform.pas"/> + <IsPartOfProject Value="True"/> + <HasResources Value="True"/> + </Unit6> + <Unit7> + <Filename Value="snumformatform.pas"/> + <IsPartOfProject Value="True"/> + <HasResources Value="True"/> + </Unit7> + <Unit8> + <Filename Value="ssearchform.pas"/> + <IsPartOfProject Value="True"/> + <HasResources Value="True"/> + </Unit8> + <Unit9> + <Filename Value="ssortparamsform.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="SortParamsForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="sSortParamsForm"/> + </Unit9> + <Unit10> + <Filename Value="sutils.pas"/> + <IsPartOfProject Value="True"/> + </Unit10> + <Unit11> + <Filename Value="sabout.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="AboutForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="sAbout"/> + </Unit11> + <Unit12> + <Filename Value="scolwidthform.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="ColWidthForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="sColWidthForm"/> + </Unit12> + <Unit13> + <Filename Value="srowheightform.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="RowHeightForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="sRowHeightForm"/> + </Unit13> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="bin\$(TargetCPU)-$(TargetOS)\spready"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <CodeGeneration> + <SmartLinkUnit Value="True"/> + </CodeGeneration> + <Linking> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + </CompilerOptions> + <Debugging> + <Exceptions Count="3"> + <Item1> + <Name Value="EAbort"/> + </Item1> + <Item2> + <Name Value="ECodetoolError"/> + </Item2> + <Item3> + <Name Value="EFOpenError"/> + </Item3> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/applications/spready/spready.lpr b/applications/spready/spready.lpr new file mode 100644 index 000000000..5770ecb98 --- /dev/null +++ b/applications/spready/spready.lpr @@ -0,0 +1,21 @@ +program spready; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX}{$IFDEF UseCThreads} + cthreads, + {$ENDIF}{$ENDIF} + Interfaces, // this includes the LCL widgetset + Forms, smain, sColWidthForm; + +{$R *.res} + +begin + RequireDerivedFormResource := True; + Application.Initialize; + Application.CreateForm(TMainForm, MainForm); + MainForm.BeforeRun; + Application.Run; +end. + diff --git a/applications/spready/spready.res b/applications/spready/spready.res new file mode 100644 index 0000000000000000000000000000000000000000..0a79a679ea2327c18cddaebfe64455586b8175d2 GIT binary patch literal 101776 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 KAVz~WRv(?+ew!z89JdxE&5LpLxJ zDX1RlC5b*RV-&15jYrZ+MQM=XOKT=Z-OG2e?j40Zrt65FqKVnoIkB~Nc^18;@?&!Y zn~JkqB+rUdIrB@`aRGXJg;Q?5OtFwAb|?Tb@%U1H`n%S62{IyuD2?lWq}I{?*a;Vg zD^c+#*|$=U1+6JCPn+bBDy6?Aez07(duvC4?=H`%qJCRczsI}Bnwo0?hqnQM><s)a zKxhPU0#Hz}>fwsfE7ai(JdsA=HHw%7n+cy4(y9M2dyY+6;(FSMv9yNHNQm8nq6l|b z$OC#d)l_ud2jb4F)cU7|dINLv?b^FN_!-t;Xe7!}RTP5gl8J6}kZ91rP&Ok6x4mpe zz<$t}E4J_9jk*NDRRRfFA~OlTRMWGtr1I{PrP>d(h1Z(6G?ausZ;`cEzSH~gp~}{9 z62GOJg!En*^<BCqS8Y;;LZRq}2_dv9&6%uB0v&_R1&GlDw8njv1e}+9e7VFoj-Cjk zW2b1PzE+&!*Z11yoxe-ZXNDjw)Ju7$qo{(sYt6PcgT{qGX-lMd)QdU##mZ?Fn-Nb3 zttPBEgc^}#P{;$`W9<0|&709jBzI4iAF85#SK-KUiMkKdX3!gRz;gt(wL_lMD!HT* zp=ioT>?q6C89D9n+{Q){wXRpg6!KaM3OQ#LN)QefBeNgbh)c<ABW40Kdmh|M(nGf& zF>Yw-@0y+ae4O(hs8{eBiz8(RaUzs1-{#zF#b5{1ODj~mDH0Llebp4%k%FBC2Surt z?hmXt%PHd1+Y^~sO-aE1Yi8qw!UNg|mRJWQq;i;ikk=IIqi+rm_3-$<r+{4V={A0^ z4DW3M9lza{5OZ?j-Mok5K5WbU=(IDCGZ5JvDtGL=kJYRUD5j<vmtD6)Tud1rW(NS? z)cd7uJt27#+9J`J%+--=jm!Ey-cN5uPquVCew6#Z!r+o4@cw`sm`4VAHtQ<L{Lyd9 z^6*o*b+w35=;+*s>UZl5MAnY9sHLzh^iP$o39Y@om78o*L@wP=?z5`o{gl{Apw*fc zNHHqA4&BV{e$bHSpw=8hma2rYp!Jo|ne=VdSLV=yXNGQ@I@s_+@Z`m_94e+3@z3L; zYLuC4$f+o(XWPy(lK>dLzIvv&U$MkB^gbtxF-T_dZdvTt;Oa9yttzZcBpI4icu#O@ zAcU(6pFaEYiBSpYj*1F>lVq1i>*GiKdqu<L`>kGS>a)_}7I&n0uPT)~uWoByeSDu9 zpO@y=OWs{vcrn6RZiQ>#EG=@O?CGN_2RgIY3u`HoQd6s(37=S>iA7~6-3Zzi#5i>v zQb#oJA%Cn}q5cNz^68I5-CZfp_fw)OuQT7VmBQd$8pdxWzxiGmOWH2o$!o6aQ`Dsm zX3*eSA|QDq^qt%$^JF&TCxL5kJC8!4B093PZ4T)|B3UyUygskYd|PIQgM)oj7s7=- z!rKr{h%NQ1&(PdIf9JG8S;-OW#%aXj{nARCNunbAY9b9S<%oBkPwrk~tMOsKorgtl z-!Rjd66Sl~w~kx}0^gJR@^JaIoC130cuh1BQKjf|*V&ShVFrPa+eZCY+|3Fvc3DAg z3Uj=C{)F%YyZJLpuS_!XZVe03omXUgo!0m&-5;a=im`EtT^0!eNlX|44fK))ppIce zKs9$j`@_eMNUn|H54{iBXUCHRQ~N6Mvk5P=<_L0z#<4^VbboBjHS!cG!#jnIyCU^v zz1MV@oRB=6Ga=22^_EE%#kS*RB~^4rPaQuElqI+mWl5;U!HaMf4wx7$=<JEo)l5IG zl!3w|Mk0{Z(x)-2FD)RL67D@Lxq~ZZ*rjUVH<*qrMu)l22cFy*UP-9D{;^d)`{SA* z0V~a8#~oChu2D)6!n<uuDxlUDj|8ZjjMg#4Z05V+%(J5%A$1>tYxK!?R$|KstA1*# zWF|Q<->({F=LAaTHVJ9Y@r=H<@PAUtHRGz#U`=nYgt_w3tg(X)7<Z{B@M-TQsb8&Q zs_RI(r=W#pPMzv&6dld#SUZ$`B=PwcVM{kgOZUyEy7G7OA5eAV(022`lPxOrRk{8t z`FWz?*t;htE*J66_aBqIhX4}DP9V@6(oJ-vqS08Wm9fZih|8$9ku~z*g5Iff#*r?} zdD`oYIJaib6mrEsomhWTTinUj)qL#nJ>oiPGh02WrnZAbAIJ{M4{0KVe0)gK(fCIX zowhu-H2SGA-iz*G!0_e9>?`#B(#R^VtL5nC83b*efXl|L&coytbKV#&-I}AuiNSF< zF-t4D3vaUmGO<D;d}T>m{Ur9!wln1F64T32<)N+3b-9j7_$j+@W^U*Xh-^CNX;ucE zQ*3E7C_rq))&_dry8M<;7;%+4$U&tb?`Q&9N!97>BW{<LURImAd|I^9$!5VjcflV$ z_2O*5wj$=+?PlRL$WNb+2+a(UNlcfhexr3t(aeRqZTGFY0-LJ6r`AJ^N$N}+B{|C$ zwe%9i##1OV7}OEq4;>U$V(C$tCcS!ygOf*@a|U_w=*@R+y2&(XH_6XJov(&=K1WVD zI+w63`z=&GnqkXN*qS)X#(TkY;SdyZz-~7`x1#P`?~8cDf!lcTIHoyu<b$LGC$L+^ z-pln{G4%BZ)>XBMJ$5=?Xfx8Q-|=y+YX+NKlqh4dNS0~}YbT76uFUNUhn!{vXTZWM znt*N2(F$+d-J7m>`A3XIT&$&ocr9~V-n=Sx4?03Yj+w(L7UIscJW(7J+PwNMcE#{y zTb0;4+a=wQ+Su~L(&jU@{OQ$v0r*xTt%#jbXoyejp3-B~ko%I?)Kj^z-zopF@p*W> z?A7=ngGU}^-@|Q>_k_j|6AbxlJ8e-HrjcCEM4YnTpX#{PsI%@;D~f8{hU6Y5$Y3Zu zNox3-y#5%c53jqqgWU;ewsCar$LW{3g1KDf#Xr+Yj5-;3xq>($<+g~<GZJ2OZ4Ei* zWUE?E`KOdzl`df+Ts|V_)*61Id>0#o%>(CVYTlC-9J}3h+q#9B#r_>D&RPmu-GqF6 zgCi#I&_|BvpKEei6(2|ldJswLlEgR}zbk`dlQ>YE5@Tzua|eQ@>4-x)x;F7*kFfPv z3%5P=!io@IYlbZ)Urud1-)xGEwX#D>JzkF`l?YFs=LUJ2C0pycD=q0C8|rk@bckd6 zR+XwcT5OHtFTW_QF0l_lly5vYTb~lmidE80ro%-Y5=rlQ2>FSoaZHoNot7=ziYM_w z^9K1YjVt^%lwtWU<dk7({^J<sL@G1w?)Q57__?enDdo)<mh5BQlZTZ>+j!8Gu2<T~ zpDy11xNB8qmb84YIwjr=5nx*Oh|518yKrH^7=4VB<+DOzU5SR7)lShtbSvgojo!6V zu|8E2s-}i^(_HhmcgzlhJ1Y2B)w3#(`S}|#PDDblL8<7Rd0f7p+%;b@9DvixLuF1# zjhfz}eXv~9-+ow17cd_iA+B*MNV*WncCV_fC!O0&yQclA=#iJ(U6MynF_A8f&yRje zV09jw9z88HNGnf5AWU|RR}k8nb@Jh^NJ3&xH}pWjqqi`dU0I{?HSS4KWE(n4_#y*W zThRD5U^zq?mbuVQbGMJbXWotycXFN_omAqo>1F-0M(9e;f&w#Hp%Cvxe|lTYjUHU} zyr)h!G2+_RWdZe0*OF4RUzoj6$9hSMk8bZTq^mGq8EyB|O7|gRTodKgVFq4JU1(7z zMAS$^ZYaQAi+MYv2i0(Kix)M_<1yDwP~nr`#V4*lZA+4pyHu6KO)i4l*G(+-Y-B0+ zs^KyPaEku;n$b<=I!Uu(kDhnrlH2!v&H!$$EdARX&#J5D&aCrpGtIR~$AwObd`w&x zQSB*n%y_;nH#@NH8f>0A@5haQ3ZMs^@lTYJ1oFu16vv~xvo!>2q7kcYO`^GD70B?_ zxp$&P1SV>@^@TR_oBWk2k7F)Ar@#n}MrF$MX)PRTt<6GNvy;3m3R8ZQqbbmoMa7Ej zSq56uFB9KO+hRe*7eBot7hmS96JpHw#3<pT5e^_rReaZP#=~aR;|NCW{p9>Ok|jO4 z6A1kS{RzP_BzG3IB1tA^(homqnBYM^rlFpdEEy=741*64pZkT4V2v#l<~Z0~95h_L z)JpCyBXg2iitGOAN$N;eV<1bD{hs*_$GqAo-UXf>f|w+tr^Fa))Vn9G8rA9vSWa5p zIBC(?b0os1UZBX!IIMVy3~A7p5N~=xajsHjx)K+M-o9VDh6g)1&eGB%EmbVy#T#y5 zD;x4HPLJ;RcthcmURfwcAp?vI_YYk8G|lizgd)QwG{Y20O~gRn-cy>!-L?^U%#%6$ z;`%TxYP8@u($E~&B<ZZ!?v?9Mv{h(%O1xfQn8LVNw-k4)@!%3Gp@)iSd-0@RkykbG zxURl7*UfU->0^S)9nbF<VJp*{Bnhxpe86h1YdJaHy}eTbak4uhe+w5n(tNf$1C&qa zgpS^UmW2z0YjnqtBjde{`$}i#tXarw1UJ^NgS=LZ2xm0!xe7<!g1gj#QskWe>vZG& zSJE3=vNhgpu*G)~OJu%Z!NAxFv&LDc0BJU_V#^d|9#Ki%?&vI}Q=w^{pmC~R)mK1w zbG=wDS=rSli;szklzEC6eA45AJaDaMwJz9hC*5tyPYXH?E3|?l!gD|s(U^zB;A69p zRlJLo@=VlHhD^cg?LZ<cuo7t~JX<+Bre~Uy>DkgXQ`B6vq)2;4mA3X3bJdb>w|74O z$HBEq`K>-C8yqv0L1JiOrO{}_=d~!0q}D*EOd$-$OPr0ojz<bxKD=l(a*LRx*pe}+ z*knK;>m?^}b&5jS=#n<ZmVjno^^+`w1pH>i>^sq;IQ^#RewBBkM5`vHrY{bYQ1%fM z;X>~-9X>!gM%jinDWqEUh_*}=YlY&*pwdc2$fv<K%W<Z+&qk*Dl9*f5)_1?qc;k<? z)r2X=J)RtGauV7YA6tJteBWs#@KX*=IG<+__Y(P4%DYO|s<jKPqVeu_jGr;ElZ@F? z#;+GSWU&WovK;IpiQ&-!&R_Lbj!Yvy-z1Ol-iB6J7+TPA-Tg!;<Pv4F*hnbUKj3lv zP~S%%jQm4LVyPmIV1;&6CaWZB;9XMRHEr)~87{Y!>Ng44FE9#1LNqTU9!y<eIzj*~ zQ<2ai<oWATrL>s^pKP%hgfZSe>o;nv_vWp#D}8!2-^4Q7nZ{?ySb{ltvY{yZ;^)^z zQ5FNoQ1%OIY_Cn`C)}hln2}S>&<V>-)3$6AWN!BlK;}k?@T5Z;4|JAY|LBL2;)dmZ za9jcCP#_M?tZy$Rle%jn5th;RX8PHff4vvP^Wl7Hw#rhBO`CwpMWY_OIZO0QzebDg zL%gEm)gcRaUy=|v&X^M50mTmWMfO=5C(h>_9Bd^;O@-hq8~YexEZ#$1uJ<9Al)8bE zjZY*ONm=ao-6lgA+}2GNt|6D_N=Y3NIWnDl)7OTL5o4(iDQJZf?eJvbX}?-NNv+&0 zJL2*>>gA-Wj<_2w=9ByvNk=ZsF7^#6$XKtNTBW<u<WPqb&I=uT81vlqhA4egi#MGS zo?GwynFL$QY!Z5UEPMUBCv3V2C<g+(^z-a3k!GF~gurEj8k#GZpW`3bu>knMIsOx& zMEcMq;c*D%@M>!(BDmmi^g|EK76J-0z^i=Mh`QQbN|h5OdM+?!J5uMx!9Y>a8$Bl| z#H^Xfi<2Wf<z|^NPrm6T&sJ*8c4=C~zi{j&-j!**18s4)kCPhp7jhnbLot6JZAek! zKmf5~`=-DiajLQk+lsl()YR%IAb~xW4>^IRwP3QqP@ti_eb8(6F``nCJfAGj5VzD6 ztEM#P4gz|O6LIXA%`Bz6Oc;7-WlTB656v4x;mg~GIpev8IH8k+;ZnJJQ@G2O!rI`( ziJCr-Hp1Q1_vIRqPLa#;$%R^+l>HHSaV)2=#;N*pFkvy->q{$Gen@bre}dI%3%y-z zIw%kfu<?dGh+vjuDXc+M1~_Mcem&cK2cT`vBPvL9mVo}5vYei0p0w=@g;vh!xQ+$t zKop|Bow(h@CiDpN7#seyquqggAHwL`kCyb40xb<kw#<FATA~-)SV_~4a9`I&4qka| zbXejZt(RvhFIMN(S<K+BC;I2{QSZpBY?BL8svY#D6awF_vYp^edlKTniC8Uxrt|7D zqx4sbkmY-1LuZDnT%L!rDho5SsZ{dBO$?6jwtE~5&CI<Fw5l2QQPVr`U>jhXcT$|# zn((^pUl-5C)iyr!akA1X&AV>Q6DzK8JBQ$T=m_0?EW9M!-Ru@2)@<UYEo>74{#5HX zEShhM?eF#6D#%7z>OGW4Vr3C0rc&1Kw0NTm8<A6~klHZzfJYC=NC0MrN#r78qlGgY zZ5Vj>NC-Gp*xJIS3ZmWE0eXb3Qa?#S$UE|o12Kos`=GPRd+YjCyu{|&x+Zc1gJvvO z&>Kq#LcmMU(QBN3#u>dxZ4?bK&#OmG4&RqC-mFiWh?T|<iaG!6Z87RNlYKMA=%9dd z*O`GQrg|8~mbFFDoJJAAQW*Y<plzU8NrSLv6mu&IQlfc@gfhbWxKj4y5MD-@XfW#R z8ydSsDf2-Nn{q^yD0|gyreHUl<mnKig=E)C+h|5rH)@wA(|hIP`HjQ;Mtye1cmbR> zQE%F|0G`v5=M~$mks&^Y3XNN-h0lrefvo@*#F65I`ap3^jC4&gdy8t?i_V?n3I%I1 ztD7)V6^Az^>7duMLhmr(zNba6aI_xm?XFUa;P(Wgb&Sj%6OcHmcJutqA&JwM=F89- zF0a?B+(uVW!d(a1x=efx5nvr-8^x^fR`(XI$-`XEl&Vmy;3JvLslECNQg~C98Ufbm zkJ5NOZif{Cdwi*rYIPGsaxE%Q#EI`XlLX!vW>55@K0Ev_GHgabjU*arY>UNsC-d2D zdGoxHZraJ0Erg{S?)iAm)5<etU0zGn;$As3JQ^-i=tCI^M=N~B2w8_R7@#-rghM%F zC`Oem7dt<mqQ(qUmm#OOx7J0*aS6$g;+uGzlDKs-)+siY#qA)ZD*f2;#riNw05c6} zb@hSOWan|>QJsarg5mzoJUOZX1iB{6b+>G7J^6N8^T9C}Lc^%3GC{Yo*GM5ti%^`_ zM?n!ET83}y9VJAWS4vx?_>m;hqT*PRaD$KZV_JS-nG0jlRS294In|<;TEfnnd3I$o zW&$K4`tX>=3G{&s)LsMvoE#+x>^zUWO64wY(O0qvSt+T_5Q=iTV$w$lA<L2x4#mBQ zE^}kG;7@tD$V5MHH*Z7~@Yv#}DAl^Gp2cIPI_xI)d7gYcjrDj<*3A8*b?DUzCenMH z{R#2iSq*JKC0&hQuD4m+nbXh%Pr*mUL<O4|s{*Y_(5aetR_3uA&PT}GF3lpG3~9$A zN-+%(z|aefmQ-$MJ!>5-9-QSzqqlZZ2Gh@WjK*#}T_h(=tIfqgUAj#A{v$pV$p|67 ziMdEGRaHH7?}H;LgkeG!WbUT{ufW0*sV0v61y93ADg=Gc=!qX{(3iFvR1fw-ufq1d z<W&mO@qhg}(_bRd$uQtV@=Ml1{gLKwXJo2@teNcrrHI(#0_B5|#=&vvn9iHfTM$>* zOF4U>kA3<(q0`O@zz8u`0(deb>mywb6ZSn-FA5A{jKT}PQ{}Etv}-HXm+aPwLBG5^ zMEIP=6QX&BK_cw!YNhgV(yX{3Og6+zU*Ixr%^~<rhSy7F$Dw@(2Yif<jTj;v^F%$T zjN!z|;Ld+@23Z#=l}HuH^+AdpI+Pj4v);iZ3i*Vw1cjHN?=P%G5UhFr$#cP6T`s3W z@(@rQK?qrWXp9RL22s{n_=N5|Oae?ifjpqPI7&bD9Sgdj|9n&GOED=a*L-|5|En?_ zG=FPZtFR8D;3CH;$@zY1mB}~Cc!O6DX@+s3&t%250hdT?t^+$Z&KUuwGNZF1(0e>P z1|5T5Cjk>q6f0s8vmGOYNUG({d~KqlCUOb`g$+cs7Gs%E)~o?(n9e@V8IsRyodS_~ zLHmDq=63?X#Wh)WicEa~`kj?imCctn34*`>Lqg>*-|v0-V)g592Tww6C@294_zwx^ z006q@pWi<c_(uZ&yAlYI=imub;J6TVmfP>TGIwUQGIz~&WuC4ZD%=Bbg7aVMxHI8C za9{YI|6MNsdD>qkfh1mD>@YdDGf|4%_aR&-QniHUa*ZUnpP0#jrPgP_Dmz86&Or&R zcl?szJX{C2!F}Mq@ICOoFb$X%O!Kee?;kq<9SMZWv5H11aaYEua8KUR6<aES@N95W z0qf!9tP15-q5PL?15`%4sP82>zu&gk?);^Hy`u^U(|~EkD05H3wBcv`cewwD>VGPM ztFmmTAX}}4ZMO2_*)Lc_m^Qkd2VZ(<g0C*=fK8Wl!DjCZ;A<a!u*FvoZ1FPy+x?CA zQp;t1@HLd+`etw4y}nJ*J@CCR+|GT`8Hiqmtpb>$3Ht@ETKJj&DZl^R_t!|^svI}v zb!D#HTN(m0<q+;@7;jI_J^WxiI|5C?t`IA*H~b>l7hw<fM>>E5QBL5%b!TuO+65en zaRUdhyFz6bsO${BiF5?}ui1lrS1*FyVK!jb6$`Kp(vfB#J@A#6Hlz<4AlmgDSOz^S z;k@9?btSG`n1{b+H2+ZfcO(#{%;kMkjc@vymHg)y5GGBRE`aTUCSWIoci%O;J&cEM zxPc?Fp5R#gC2%a^5;%U#2OLj?lkZ*{gRe=x-~?QE%X_ciNW3RF66XO9--LC;1$-0b z2=+qy0MqRVGTrkNu#UZOQ3H!C&wReA$~z77^6&8ePv8Gs0w^t3oM<KPyevKOWi*5V zY?rM8#$XSG5scT!O?Pk<!g~+vJ-mIvF$iBc!PvuCPr&ss-jGg=C49jh){&98OW-J^ zFC(!Yduce<eNPWyKk+8o3DPSEum|!BupYGdT!7{mjlFe4)&=opm?xOG|9oWs-1%n` z2tCVvELw@HE#LI?CcI{A@zvk+@37w<hHxK&Fodxmjq`@CaQadniT47>V!gg#8|Ml2 zh3y+oFuv~K5acIdU$H+Q3_)`OJTJid1kV+N(A=;$Z@}|Igu~wa&=qU}w)z=?uROK( z)|dGvr#E5VU>^T$9RIZc`w|G3XXS+U?qelZa=Z18%HS&xEwCrldJmgD{9yd|>=nWk z#`0U3M#FPGgylY_kWIt5!uqo}_e1Lg7~g(qtpMBl-dX^fOW^qgUK79xo(p=yY{Bjj z>%H|stDhkV&p+@U66Ou&5$5&ZAK^cDd`|+fJa4G-&Q?O}?=SmyWytmn_ppN3ZTsuD zJv;p_rVe0xs12B4q6GS>OMrHA{NP1dKF~*13=Gqj0h7#>z;aK0ushUhPp@Fzg7e+b z6`uRyb!2ylCD;{g33kE>S{rr*nSt#n6KKt;1@Wc4#~aKe%<Dfo@I5sDy?WT6!Zx*! z{TKXIz%~f~zH1kMu~FDw?ZDn&>=d?9c+KAvZVUFpwhG~RT~7{FU}prSS&-oAQ%F$q zBrPb(Obg}dKv}3x21;-l&YOvIfT0?aV2-sa_|n&KZyy1#E!&~}L|cFfwB9g*uEx;b zzzEVqgWuo}^9S<^^Zd_T@b6*$``%yHdR%R=UxnqmpJ4yr4DHW5ubA)IXLlIniy=Gh zf^hB%hSM*0dIh#qb1>+fI4BL_EOCP7yGeYnjT&nIlB6O1*w1V6odBbCq`+Da?Jscx zXg~NRR&W7q^49s)|L^k$Utyl%^}s)C!r!C%^JREVoo^zw`L$g4@(}(npx7N8&w*_a zwo7=g-?3+-kexz4xeZQ`jovX=0wsUJRQxzK_$5(6*Y6}Is2)mUdx;XdQbJ`)hz1oX z0o`LQ&IYC%%7AEh4e+JA=3dO90g4y?fk#LOVBX;|{QQXj>A5cfcu#%zg4pu6<O<ip zJ^<~i{!4sM_g`_nUt)Q$p;+E)Xn$~?n`sZv-(w2nx|bNCD<j2klIT}uQ3eVSE{igd z?<H|23Q(Mp9F$|G2L0r@!RlY;{qOM!kKv#Az&@%!cZFkWH&l71zbDiEdRPbGxIOF( z(C%Miy>M&>POqR;>8u7}`~};6Ouyjy1<QR*|8S*;+V>I}C_?}JBo66>3L7o>$W;29 z_P@_3JeGgrgg=Kp+$&0v^U+fa+0Xm(`_Z-b7hkY{zSH0W>x0^!P9*6{{A#yf@Fd^E zQ}hRz{s`~AHYDl4bOOqYF_3|0Pf<f>hw|Um0eCF%n0{UY-|q>6APtnX{;sLJ;)!#T zw%E##F#l#7<O}Mc^IUiz2A|u(zM%q&(<`#jfUuqZ5LXz}uW{Ye4;bfP>i65fbA{=< zO0j(xf0*BRb^h7E;>-xbJ-WLz1^m0FG|RJl=kVXe7?R^p*TcF1>A*c>>Am^-i_QNW zo_o6R9jw3CCUb%kgniNX_=Ddqh*ILJ|Gs7aTnmK%!-p;+;NLObu@V4NwFSQ`!|%!V z&+6kfMWFc{n#cc5O#j{fB|n%0U>;L61sB6*S;c-1>2LS?JL4a(%?p;>e19JOGn{|a z9<46;U)O;jtpQ-(;IT!ka8-R9*`KTZ8vpVLBXDl;_5VrQ_djKS5f3x{O<<D#kJr&( z<NF+%+XEGNKqY8?mxT6X(#I)5Gr<$!&GSOv^&fJ~RR1*}0Ivam<p1}1k5S>7`k%Z@ z_BH<1aduGg|K_)k|6j$!NXrZGzS)`YVz)0p_?oOE1}Z@EhS%O-`)Jt5!^uwU6bQcu z^z}V(UZ0ooH~qi9_kWUy*MGr^ynlG!@1GBs@9K)I!0!|OoVEY47lih&^Z#EZ`~O6P z{%ZV-!ac!aE4e?F;X@N>JqOAANAo${ZYps6547yXS^iS|Vf};okUvQUmi^?s1&<Mm z3qSZHvOibzcg6p<$(OUeZ`sU#T{ZNMt~xv2AME~HwhQA@Wcgctx+r?;e~dq@Tk!Lw zptzE?$Vo6oSL~<!{{9%?EBs#Z&!PRtUVlgYX9j!0Eb~9d-ye#%?#usMn15Xd_X|49 z^BW%kmw)#DuW9Y)VS9%$zpF0^*4Te}hx}_?e>R_@B{ct^eqZo+#J{Jy_)lY~ux#Nu ze;<oKyTbOLtS$N*{GV9J{czs+5lt9-c>egAHQt};0sMUd{Ef*Ut^3bw{*L%J<|OZZ zckv^+!Snu)@cFt8w(;++$8Vey+S7p_tslOo1?ORU@Y?aOz#bkW{EZ3xozb78{l^}E zNBm2p{lHSIAFuu4z22YsZWvQI!9My&v6uuX9&`rU3&MSWzlZo1_OeiH?<wRvex#rO zP8&Q{=>3q)Kcf5RHGfC^A6~KmtG=;c`&y=dws(Vd1IFo=mdH=x1ji5HSb?JiE2wbt z%e(^X0!#-^5>QM5)&)HtM)*DN-_V51us*_TQ59BNP!&1@^pxfR3(RGI)9-8kzs|#B zh1P&Ie~$Jad;A^ozhei#KllCEIox&{T5tc}HsSKm+Weo<FNEwHjuFB*dPuYH;rkFe zJNW&5vFC;Np80!U1eal60)MyW{Qdp=W%!%ZKcf5RHGfC^Gp*JBAm@EK!B^P#?qk1? z_x=^0=YPM>`}*F$GJnrVY7gUmUcPmO`AYiTy7OB+z~3GJIof~h@&8BsVR^!`wi0Fr zQ+37n)?(UR^kAHZ@c(EZ_AOj~RCgWn55Kqj-|GO3KO7q<xB2mY_OHPIvG*AejsgB( zr2Y8cU%|sID2DPQxx@3SizFLZ{>%H{KkED6Y=h^AKf`}tA7EecBVPUr|G$sH|LfOy zE#5y}|NTgo-)hS<l>u)<=LGP44bS8MlX%TOeb}b=*M<8yf9ndbBjGdW{ri4@{j1i0 z|F7e|&wr90-=FUPelNrCmEkj3+h5|murJ=XS9os_p(^k{)&plr)?aCU3wyW@){#&p zzVG7y&;Acu#eDVqnfTB5@cz0UUK_yY!26j09v|2)y<|APi_6!vzL$r6$?xg@z6|Rf z9Ao$%jep`lUx5#0e>VR6J$b_Q@OdwMz7Na(_jr6=hTFg1*TFG8c%Fb$`UUa5*#3`V zNAR=YSj3;jjo|&{_xSxM{`*_}fA;+6d-8<q!&UgdYxiH{|Npgj-C<Q7+a90qz1;WL z&He7XFS%(N6KmAiqS8S{j0!d^pdzR!hz%?lL_~~YMX(n@il~5C5EMJoK|zWlA_(?| z(P*OP#=F;BYtEU?K8JG<2<1fg{=VOtvS-$;S!>Pgnb|Y@ke~Vq%0u7taKt?$WD`=m zp|ysZ_K}dSNYhK{lU>l<q$XbF_dlxor%-L)|JEc^TJzPW6RCd4zt7&B>4)^B=~=<; zfow`!nKs{Q&MUPqZF%MQzt#0$+x;KfWI6)ZV%7Dm9wuE+?c1K|l=^*5x|il5I|#Ki z(P#sa6RWQUQTnmn+h|PB`Ih&8RM$Pl)Mft{m!;_9K5tuGr>|*`Kk0_X<ws~w2&PZK zc|uL;>7F6><<2;lp!AyHi+jH4d;v>K=@Hv#?T^x<eQAQc|4Xy}|NZ;#uxpZ*y}wHN zv+uYmzu`vTX%m6xyk?qo#xs0$&O<ZkjMvsN#`tZpVGR2n2WU+zrD4^%m6#_L&zV&N ze*3}0qB|HM{b5~OL$Z=S@v6xV<o%zT^-r-eo=(;Gf1~b6XQ?RXH2mI98lJgL!*746 zW7mZK>^!F-p6Aqr;oZK1bdRwjj?A#Go(|818miz^n56#=WZ<`@7=EyW3=aH`T!s>E z7QL|SPhp4sK%_s8@kn-}ZUYUy|NC9q|4I74U6=zAj*@q+q<cEwiFzlw(zh70mP~>y zZwJU)>ZpP=F9-Jh1|vMjuMRUj`|mZ(7_xn)h}h#i9E|aM4@T`2Aip|HJG6pzb_3zU z@@W!GNB?xV_+u3oS{cEp-kl)ZcRHg_e3E^V-Aem_hCcuCuIZm_VE+Qgs`Fo{e`@y` z`0d8*rIX>}3Kz)nbA_B$vmkf%Y*nn84P*4Xf^kP2m#e{~QybVj*A6bNoh!oLv?rK; z(*{g1E!|g#={H}24bsb5>kgOJ&x1UFDduBXi46;2oAYQ0pF5tV$;C3rJ~FXyNX73F zvOWOE0*!J0>s{1;<;^nK?SSI|-uCG`3tsk+vvLOHp{(;aE`owho(gPU3<VM_v>6Cy zUD|?q*LE<VTL*@I-?j%EqaKjE(Gv={E@3#ad^VVNY4=tfT7ut>*|roeZ}+Lfj%9FJ z4OxMnia1PHxW$Xv7}+c91F-+1x-{VVPjUZ$L!G^;&lw`VcHbC0;6E_HQQRZN`hM(3 zvwbGBHb}ZC3R(e0A%1W*WK|V*qaU$m+E_5}))D%5?*wb7+cK<o!Ed!}Uk=4#YefXj zp9%wdb_O#{TOFOi9P=-+9|6VT>k#X!5P^Oru0{BR0vpgJ__Opy!7G`KUhs8-bo^cn zJp+z9Sv2JNZ&CkT2k)A@Z<ap3x9cV9|AH@mYYW>w>G)b?0F><81lRX(u0j<05xW<= zf_ab5;5zDi3~yB+8eK$b)HW!MRv><@7xe4d712c%y)X{3b%8UK9@xQ9hHhD`HtfWE zN*ve;r7_#!+MW%pkD>8F`a;w{w*SCkJsa%%5BP|D=k-ta9PH2=_DnEgV`&<<6>R*0 zwL{X!jl&^`-B5lcRDn2j5pn)L(C@o$uzw|f_mSTtm)#FTSBaxx5VLv-*bf=N(o>!R zeR{wkgI*9HxEw0tBdU;qenR}7DkPvkAyN$yjHi-)8}S+74b=Xr|KBs-<f*?^56|j5 zdFmG<)qlM2$Y%Qv0Pk}elZVJTHW24Bn2q`A*<T#Cp6UMPvAu9BaX%tTffLbi3y~4A z1;!7tfC`FN#&P%d$rw<@0Sq4idn-%SeNPx@@Ex2B4uIRIFrMRdEZnY!gBT~l8KocT zR~(IilD&bDALxNRJHU}?gI;a0>Upq!n%104s{eO!{D<`uuQ$K{3nJ&(!D)9JHtwfq z>y1MpOpkZY9)`O~afqWLt{sbp*g!wHdmiJIxOYAtsv#NU5Gi}MgM~qFhRC(P7?+@i zV;EK<1zk1VPdyF<%18W^$A#lFYBigeoN>1i0*8H<w{h0@A86KO{bEr#V*mfH>z@qa z*JnRLn9E2=U2M<B0QB6aHcc{rkbVjtWJ+-w?q^W=w1|h9XP_FgFb?6jU^ZA7^@Xj= zJTZJ$f^+CcWGf-{E8`wzCjo)dJV-kQx3M26jo!}YBWa5rVDo6hn}N3dKdPUWwdZ=@ z^iMYM=*Be&n?4*emN~(d9lq=tK<%4k|M+4GJkCjl$GK_n_>w9rFQtQsJo0B$Auj_; z&L=`*_%5hKKSMsbnX1UogeUn~RVYBe5|x;q%BMb{{75)l+4UpxI30G_nLpfYYt|E4 zZ}30-dLQ-AZD7yrv5<=LEecx6#%K4_PB8ucRCob?x{_OkqFi`dbV(Ig^Wdoz#Tc#? z@-bZ%o)s4;!bpqkfclo3$M)e|bTy><I^#Di`rlIOUh$`J+M9B{?!2%1CmWz=LA1vd zIJ*>WVAl#Zo~OQ-^ziIj0sLHA1V5Kuh3D$HQ4G(k;TpzCP+kJhC3t~;O`tqf4%r($ zLuejA_ITQB3PjEw|18Yi;ZtO_!P`AImiJlzWCJuNJicx*BzR6{Yi%?iq-Q}T_R~LK zzXC5RO5vB=<?zd$3i$QTO$F|vtB!lO;8zvg#&8v0-mmhrc+CIH?HkOto?w4N<HEAo zT{zeGh9mQAA=uFje*f+D!N$}**}(g*f3g9(F2sgG$Yfk6UXI`T4)$YX?+588v0Ywd z?V9xe^1&T=_3$3Ndh`HZJyxRf0la?vunLur;I#;h=YC8>`CdM_$L!=q#dY>Pp|K^c z1<?9q$_iHqbs7qx(~Kczo)NJX&D&{Xxl{(9d%q9ke-f&;YyTW$TqiPx2<M@Y;WrcQ zKruh0IpO2nRG?=y^#|0>NsnX$O!rL3k5SiBpdFCT$xhH_sLj8)S&Gk<LN>0XIV7z+ z(b{vy%2^OIe<JonUU16a8DiXx*!TF5Pg(!kl+_6F)DB4YduJKJ!6mM6z|9uYeei#p z0vADX=vugOFbLOjV%hwR?BU7f3vA5ytfUa1;aAvLfyN8;Jf}Ds4^kRR%jR^r_Cqv? z7SSZyv2J#7(AyO%Z{1)uI=6YI_$@|R|BayJ8c6bfkX*X%T)70XsGD%-k#N}E7S7{5 zJQv>!lkTqU^kwgV=-mOW=TlqeYsBQIIJ!sgi6|}Qp}a(cXc0}KO=U<g>Vr8S7%#Vf zsc;(E&*jeb&x@nIWaT;Okg&!Rf}N}&+I1wvxekL9ZlfW|1NZHCJL3BMR0QtjV3^9{ z=pLn^w3LVP5)Gn7G&Nn#ssF}Ydw<*ag}Ll?fd}HHCVtbx{ov$A4~Sdt0@3&%KVdG` z5IlJhjvWRlfPRXjdz6OKQl6S<@_ST&E(^4eCT;(`T-nu)?;*?j*9|>1S9@q`{p-T_ ze|3Qe(szCKFf~LT+W*Aut*Q0@zR&-;+{taOt2xJivi_@{H?sblRsy{3>4FW)?Z0Vt zPo>HFSIAuM|C|3m2;}xJxBsS>fZYD6-O0~?dHuh++8!T+$o+rQYk<pMZvS%oZ+h!f zl*nyRZvRcM0WN#F{Wo9x=Q@zxs&&BTlm)gz`TZ}>37S&}%~^I+>%Sqsy-odheZb|c z3p@}n^{GQc<e~a=Sv0l&iT~!hc%5~D2jZo<E~-D51@h3O{l6~AUKe<f_22Z?&uw1T zzuf+t-ue_JavPM}f75G#%U*8(a{F(3>yz6*wLe{Gd%D1b-2XRy3zYkRh0MwRxhyb7 zp8qwWDRQ~X?Y{|yt}KenUhe<p_TTi@rznxz;QQMCb>ZwyV|@R&w&!xB`mb%ChE7L1 z;C!G}HtF-9mn*xv@y=1!zi#NEx!QxQe_8*H_1z~<mu#%L>{~9kX8V@gf6elF*X>8v zzpQ`WPdAn;_y4+UV{-e~UEMUrvq#pytpCR9_c>j;|JPj`liR=U>PGJW-*4T>`j_?J z*ft>d|L?br$@-V|&&TPF<;vrK-L)~f{p+r78vEH#^qWZk`c#e#os@xoWA*zoU0DLM z1Y`-w5|AYzOF))@ECE>pvIJxa$P$nxAWJ}&fGh!70<r{T3CI$VB_K;cmVhh)Spu>I zWC_R;kR>2XK$d_k0a*gF1awaVv}sJs<<mmt#%n#jR?>(HJ-rX4VIMs`X$FDny0j|6 z8w#6Ng`ZLQuT|j+3QGtkQMhH*eIE)-3ZS5#o_L=XCn-=p%!-#VfVH8k6(=Bu8DEN< z`1@C=IsAdzef4llwfl7qw@}Ofu7&F=5B2ow@>UPOO@FP_<f|SwRlC3REn!f*uNFr8 zRk0_uZ<R3Gze*U}ha46gBkM0@dC2k*B~Xj@!8>@_)hL1eZT0k8qdWmxGLUFL{E&VX zR|j;uAsi4bSV}!TAIzg`*K&(49|l_Wu--YUw`a(hz5yX)^aIFGaVssmN@}EAoNu)5 z*(1WvDEioR%U5ahMnaay7|32Ujv$af&3%NBFwOGS9!#@oSkE51!u<-%E`LE8Z%T3- z@uqOaG@)d}T;ay1g+lq3MM`*Jc!6*|z+Jey##PAkaS+bVwtho-)(rmkFU?txb%VS8 zJ<`r7gJfLdKNre2&WF;#`9f)cI~1*(18K{qLGDTyp?KXaC|)~@_=loZGoawdsY3ev zQ9yYEth)cbIqE=ir}EFw8VnZ~j~A}^xxi&VXSj?yh;$wfgSxZ<llGs3NxRR5!RU83 z>n8Y*?FXmaM?;R+1R-OA4V<4jnAKt3kZw(`hoI4YH(~h#A!Uvg*|>1Q(^g1dI93?g z@e9G|t4|RB6buP%2p=;Tp*vZ>gAhBpKg&z`Ly(p>9SHya_vqhVK952~D<Sn$91n9> z8mG};mUZsbNoPwTdDajhoS!|Exhd$LbR7)lZT|@dtv^Ei9~geAa1FSNapWJ=;Zry> z<9pJ9aANwvH=DJz>0h4Qqwnkq2Nsxt5>h|K@i2EG+TBn%FyBN|dX^?~vN6-W$UoXa zypsi-bwz&Ao+2ljf$3KtGye5k{X@m2I`Oyz4*eMaL?^=5P~$gek^iVT@1a6nF8r3a zaQ|wC#w;(N|12a-AB23O+!5Gc!np2jzySHQX!i*Ojl;TO{KQ^gGroymO(6N7#d>oa zJUXTSYyTnLsy!b_{=`3jXcAN0Pc9F0m*SNClUKaY{bgB6kVNGok0du2!wxF^+4g9| z;-~g)rxMTWFrnvHuywQ{Bx1dp?V<gUOEl4jtkv5A@qeTN`M(sqTTw2Sc^d84w2i_} zh(BYr>$Ssrv-{DL%wcG!&sFMR{mmC}(q#~n`w8S9WiQ$f)ggFvUr$Z^H>CVCLpO;0 z2aPil`LjhEiXnSOK8P1C(>>T0{D$^|HP*f1gtH}VvC)VAZ9if8oKQ#DX2gCVY^*_m z2L7XBJ^BgxN4M4*N0*Hd(nGy8rjPe_<Z^@UqYWSg?R~ecvBIWMo@58iz7(<*(<)^R zu7({M@4O9f8mTY#qgwcnKIqY3xSSXSN=W?_$HUx(c;Asi<{lqS>4n5qt_t}he_YPQ z8~N9x?F_&+Z2tAfu+*}<N;;lq*I3k<q%U1-{hcU(E%p;d_FtE)rv9fa^PG@`ypo-W zK>n#cnkf5BY769#aqJJHy0(VF9Y2R3hx8KDkHk2Vzj2$7Al9)TlRxTA*rKKVHl+Q( zdhr~1|H<V~F4;coW0bO8*sm+BM7!s*rso(v7n1QAw|l%PSa)uPeOE`)5tBdlpEwq3 z^!}6j(c}Ox#z%_Va7bTd3mKkvkh;hYEIWS*Mr}U>vkqTC%A)bGVx$Qewfh_lF^=4* z86zOe+X1qcI>Krk3q@l%b>2wE|DGD2Uq_Y<7GC{aS!<jLoF?4NIjJ@M?fgvPB=((| zUiOe5=m7;=ycni`ZwzBhz60+G)=;=@DcG6!2D7g18C<RV!Q~yx5WaAEr!QRDxtyiJ z`Uu!Bz1cFnm&Q4PV*Fqz(Er0KA@x%n4|5k{<{1mvXK6|=ripYiMLAA}Ymos^b}$Ia z4h4hvR68h&-VQeohah&triHFBux}6W!uV^kK~NqSroho~C`Vk6+6vjrrV6{q8fYEA zHT3hB?1!#@y?!m6Sv3!?hOUJ>=i=aA$}zZ$xR-hy?x!X)WFH8F1x}OTP721QpOoMf zOJ5w}4+o|X&Db=ukJj-s^53B2A89}K^7%6%d80Rzb!A=#{8V%ao?a#7G2GA3hRQ3s z@U%D|Q2@`b6~I%(lfnzAhj2LK=Uy3XZ&Bm?rLp8s^&maG`PXl7eyb1U1+Ruj7n9+| z%~E)I{|>x-cu$G@=pr86g%`JOz~kIhDA>IY4tb1*XZOlu)t|TO;l}2l>QJ7QASAAt z3Yj76A>H2tu45axefpqiN93nCx|fA%Dl4u7_36Z$I=|{+vY*(6{e(-00&0z;KEs66 zV2@g-Kfi5`KzXQ)3sGx@vp9cG^qV0ZUp5s8<UhN4A-l)<AfAXfb$->uRL6sh`U_W2 zhl3JQKgIDdcOhZ9jgY->g{Jgk8c9A#4_z!^9-dxGQ>&kNs-^rJbo@{DLKnAx@{|2Y z|G!9jPn*9k_Csmwa@92c(L_hdzouJS<COf@%6=#<$%!r^sPHL%d6>HtThsiD=ar^! zWcf!Q@fu9F21-c%6vxBdh0_5}LV0$Aru1SONj@k(8!2EOo?c2*t6#}et@<BYPoOb0 z2kC=@;>gck^2f|K5e|7;ifPo-@-TM~{a``s71h%7`{YXLlb?7(8T@JOhw6a**GB$- z_WtM3&VPf>AF1C_zv|O}D($CM_8+^@T(}s$29%KcDUOG^3vo-Wgyfy`G^H2QNb<qC zEi;9<rPe&Xl%`fc@l;#;kDjY9h~G_;`te&w;yr1+7Jrl^Ug{TV5IreP^lMFrv}(zJ z6r)dN>lkX=f2znwB108fN#p;BUrqj6%f>QlDgS7#G^Azy5uT-ar8M8-uO<I~YWw;1 z>BDGR4@A(qAS6iq$~b<HyKMcCr$@K0@wLuRys6Ju)WbMl)W`lh3SIWCGpV2Ac$mA= zxcd0(m`DE3m%75_uq**t0?j4??7u({*oNFUdZx^MruSFoR_J}e+$6o0Rqiw5w1u9Y zii=S!Twhn69+t=GaTobuVdP8KU6LnCRJp<V?e6{$rTe)4lcZa1A6ILPGed~`xG+y+ zUw)QdS_awl85A|qWd32te!&FtQykrE%<^}S(eHNB)jBiZ*8#4qa)Ij`+yVC~!IhQM zA=i5noNyhQL1`L;2dtx0%DfTJt_RG+a^0X{wJU6L7z{fmTS4a1DNuxac5vSmoSS3) zl+rdN4^*d9E|yPle+}d;wu77{6Tx1;6BxJs6pX(91T65qq<x<b@Wa3!a2of1P+E04 zpz)a|ZJPtQo~#we{l?K8Q00C~&_YO<J4}4XOYa!Z;ocaVZ@(1Zx$`{@<hmNMcZq;@ zktDSTEZ>dFuIZxp(ogS{s3f_4DMNghztzS7ob=n{-Vh^LhwqrB<&vM?Z7v$nRq?(V z`6Qd<dZ=&t#R>Zuy?yrPVA1|lR;FX0c5KhY5Xrs>>&{=mN_;mgeHTmZ;*XY}8?u(s zr1!W~o@4K}a9p`(BzjUmR$n*M&OrQ8n%O3u;MlZ*EDyC!Y5Dchf8wGsjMjdn&+8U} z?~TLkOvEt7(>rvM0qMbWz_%L9uaEw@{CU~5Z@}#9f3kf|+i?GkNB^#DPY2y6+oSTm zm3t1P@+Uder+lgXQ5ioD?#arax>EVZxNl}qhtHTj9GPkXV{!ip?I9p}G=%-(zBfo+ z<%aK=Cqkb8Jc#q03f8?l!+OWzuwuecF!|;ym^#n^3O0E%oLw;ovhjWH;mQ50wZHo4 zpJa9>U?!w5p9U525pXp&1P-lV1~-rGg~TnZVd4-AxVU#4+)CV!h+=M*pX;kITjTEB z_Q<Vo`{SKKSyDV)$9K<93bK^QhWokcaQ8wA{B-#uB8Q;_)8vHuSDO$1(ejCp>&bDD z6S4*#<s`$aNB7~kr#~@}pW?2>?1Hl>D=JG`_lBrH5vBi{FFd{r$R?>>6ztv1Kz@p2 zwxZ}`HI`pr{gVwaJJ{$9^o-zPO)izunDwV;L`@g*B$uz*{$%~vef%M{HEMr<$o_CF zh5MAX0{0feqq01$_wQa#1xiyBjZ`c{ll@a4MDM1>^><p+Yy>FZe^={&n!9|GNpsd8 z%hzwt@=5+Qwk8{HOen|i@_Hr-Tn8>ZaEgcOD)1m`5*|+VX_16HX+lL+Jf&$_TVTGH z1fHJ!)B*8p)&EG>G5$-BF7@+hA7dO%+W9($1LkSSYleQ?K6}QSY&km3GMNyG{#l0Y z`e-Tx*Z<oh?`_cSPC$PTbw7`L`lPbg!8xN36t0*qlm^Zdiu~P#YyNKRj8X2=NkZ(5 zVfzeQ{jXy2MpI#Li3=ZRxIN7c_jCC;K-iQaf+?N>GHdr4jPKJySToW{I6HF);5oAG zoDA}5L(ho9gdNpT5Wig|?(|L{oX4|sE9|_;_A!Pye^xzXu^8uZm_~3n?!aV)^|nXa zY~K!+#V(9vdwJ;H_lw83#eF@Q!Ry!@XqIs&FhaT^wkAO52Kb!a4$nV?;(mAB4=&*O zr!7<mBsjOW^pjW4hU2)8-w5aYlkkj4JkEKk3}=H5FyFijY{s>Ml|y<m`Zy0x=JfO9 zHmk^i%PM8p0?0YAPP~^me+<sE2g2bg1K63GWrMoI5%lwUsJ-%B3eAf-eH4XTZTZg% zLHV%rMniGl-i7VY_O$56&LphHGYUai7n<+m*$iRt_`1ud{PHE?yxR!4xN-&rI#|JI zgKiM)Vgtq<zl2rxR&Z&ZI~@0Nf@HT5!UEHdOur=m+RBIIcH&28D2v?**?V_D1<w7l z(Dj?^47W}lVEZO%?{J*^xP9C{mGU8zsdl0L0NIc9dh_OY$l13I?&3b)pUaBj=kgMG zj(aYjqkAv?6r^nRh9{36cHs2uVn57y@duw*Le{~ZP;e+5@}tm=MjQ@@TUQGOsv{<8 z%jqL;Zgr6l<-f4s56HI2uMVPxmkNDKqv_HlA4*5hTe_#|QqmIX*H=D7pUaEN;eMho zl@HO!Ix)H7J#s}q%0N)IFENhpqkIIVd{olYJ(7=<J{C>wOH);u4Akw166%_K@(ynl zPOYB|2y#V#{PIyk;_3-Jp1XL?#!kR{Vpy6NX_0(Bm)a-p>us=cJ<-BTJdZ&7rG3NV zev!G#{XFDK{WP!Oang7-KhZ~;9XbE#@B64USGbn69}whf^Gok*OCumHqW>AE|7UhV z_yEUkE%e}Z3q2pKh-T2ex&ie|Yjb+eI7(@abQRwX_;2)8AE(jlrPc^OPBX(i>KD>7 zqd0VZ$klXp|Kx9f+cwT*P15`^dFSSh&f7lLc#X^0;U8h1|3H)?LbZYN9(Nv8Oz&E} zh8e?x!F^%pBuhwe8dy9-K_m3h^<21_drCyf`DpAP;#v6EYIpWLr}K7pct(?tM>dbr zhoFi5H&MBiS9;NW3C|6&sAN1#PGgK|ecQ8hdt<wO2|hSB*o$YX5?!t6<wa=4#S>!L zM62-FPAE+~#NtllIVa>5{D=1eJoCoZ(O2X7EaHXduc`dBu#I?5YCO!f>;p@Nn}B)8 z){wN=0rue;sQt6Y?Ri`IMahTZ;&xvsIS~sbClA4yh@Egh?F8fm`$2AIng!*rseBT` zgNkdAj?ZOA1L@=^9)zNlBXo=Dt)}`D?ULjeCKK{=P#&KDZRO*BD>jFv4E$2&(T(yi zB(ilHTB{*sgfE5M*!5!E#h5iLj^8J@0`uU-_^0P>UDsxmV*r-_F|HwH?_G}LvD$<3 S@bdqFTRO={Q;V;C-2VeKmFo%s literal 0 HcmV?d00001 diff --git a/applications/spready/srowheightform.lfm b/applications/spready/srowheightform.lfm new file mode 100644 index 000000000..2ef11c39a --- /dev/null +++ b/applications/spready/srowheightform.lfm @@ -0,0 +1,123 @@ +object RowHeightForm: TRowHeightForm + Left = 479 + Height = 203 + Top = 289 + Width = 325 + HorzScrollBar.Page = 304 + HorzScrollBar.Range = 304 + VertScrollBar.Page = 168 + VertScrollBar.Range = 168 + BorderStyle = bsDialog + Caption = 'RowHeightForm' + ClientHeight = 203 + ClientWidth = 325 + OnCreate = FormCreate + Position = poMainFormCenter + LCLVersion = '1.7' + object ButtonPanel1: TButtonPanel + Left = 6 + Height = 34 + Top = 163 + Width = 313 + OKButton.Name = 'OKButton' + OKButton.DefaultCaption = True + HelpButton.Name = 'HelpButton' + HelpButton.DefaultCaption = True + CloseButton.Name = 'CloseButton' + CloseButton.Caption = 'Close' + CloseButton.DefaultCaption = False + CancelButton.Name = 'CancelButton' + CancelButton.DefaultCaption = True + TabOrder = 0 + ShowButtons = [pbOK, pbCancel] + end + object EdRowHeight: TFloatSpinEdit + AnchorSideLeft.Control = LblRowHeight + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = RbCustom + AnchorSideTop.Side = asrBottom + Left = 108 + Height = 23 + Top = 121 + Width = 74 + Alignment = taRightJustify + BorderSpacing.Left = 24 + BorderSpacing.Top = 24 + BorderSpacing.Bottom = 24 + Increment = 1 + MaxValue = 100 + MinValue = 0 + TabOrder = 1 + Value = 15 + end + object LblRowHeight: TLabel + AnchorSideTop.Control = EdRowHeight + AnchorSideTop.Side = asrCenter + Left = 24 + Height = 15 + Top = 125 + Width = 60 + BorderSpacing.Left = 24 + BorderSpacing.Bottom = 24 + Caption = 'Row height' + ParentColor = False + end + object CbUnits: TComboBox + AnchorSideLeft.Control = EdRowHeight + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = EdRowHeight + AnchorSideTop.Side = asrCenter + Left = 190 + Height = 23 + Top = 121 + Width = 114 + BorderSpacing.Left = 8 + ItemHeight = 15 + OnChange = CbUnitsChange + Style = csDropDownList + TabOrder = 2 + end + object RbDefault: TRadioButton + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = Owner + Left = 24 + Height = 19 + Top = 24 + Width = 102 + BorderSpacing.Left = 24 + BorderSpacing.Top = 24 + Caption = 'Reset to default' + OnChange = RowHeightTypeChanged + TabOrder = 3 + end + object RbAuto: TRadioButton + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = RbDefault + AnchorSideTop.Side = asrBottom + Left = 24 + Height = 19 + Top = 51 + Width = 76 + BorderSpacing.Left = 24 + BorderSpacing.Top = 8 + Caption = 'Automatic' + OnChange = RowHeightTypeChanged + TabOrder = 4 + end + object RbCustom: TRadioButton + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = RbAuto + AnchorSideTop.Side = asrBottom + Left = 24 + Height = 19 + Top = 78 + Width = 62 + BorderSpacing.Left = 24 + BorderSpacing.Top = 8 + Caption = 'Custom' + Checked = True + OnChange = RowHeightTypeChanged + TabOrder = 5 + TabStop = True + end +end diff --git a/applications/spready/srowheightform.pas b/applications/spready/srowheightform.pas new file mode 100644 index 000000000..b4eb56dea --- /dev/null +++ b/applications/spready/srowheightform.pas @@ -0,0 +1,143 @@ +unit sRowHeightForm; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ButtonPanel, + StdCtrls, Spin, ExtCtrls, fpsTypes, fpspreadsheet; + +type + + { TRowHeightForm } + + TRowHeightForm = class(TForm) + ButtonPanel1: TButtonPanel; + CbUnits: TComboBox; + EdRowHeight: TFloatSpinEdit; + LblRowHeight: TLabel; + RbDefault: TRadioButton; + RbAuto: TRadioButton; + RbCustom: TRadioButton; + procedure CbUnitsChange(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure RowHeightTypeChanged(Sender: TObject); + private + FWorkbook: TsWorkbook; + FOldUnits: TsSizeUnits; + function GetRowHeight: Single; + function GetRowHeightType: TsRowHeightType; + function GetUnits: TsSizeUnits; + procedure SetRowHeight(AValue: Single); + procedure SetRowHeightType(AValue: TsRowHeightType); + procedure SetUnits(AValue: TsSizeUnits); + procedure SetWorkbook(AValue: TsWorkbook); + protected + + public + procedure SetData(AWorkbook: TsWorkbook; ARowHeight: single; + ARowHeightType: TsRowHeightType); + property RowHeight: Single read GetRowHeight; + property RowHeightType: TsRowHeightType read GetRowHeightType; + property Units: TsSizeUnits read GetUnits; + end; + +var + RowHeightForm: TRowHeightForm; + +implementation + +{$R *.lfm} + +{ TRowHeightForm } + +procedure TRowHeightForm.CbUnitsChange(Sender: TObject); +begin + if FWorkbook <> nil then + EdRowHeight.Value := FWorkbook.ConvertUnits(EdRowHeight.Value, FOldUnits, GetUnits); + FOldUnits := GetUnits; +end; + +procedure TRowHeightForm.FormCreate(Sender: TObject); +begin + CbUnits.Items.Clear; + CbUnits.Items.AddObject('Lines', TObject(PtrInt(ord(suLines)))); + CbUnits.Items.AddObject('mm', TObject(PtrInt(ord(suMillimeters)))); + CbUnits.Items.AddObject('cm', TObject(PtrInt(ord(suCentimeters)))); + CbUnits.Items.AddObject('Points', TObject(PtrInt(ord(suPoints)))); + CbUnits.Items.AddObject('Inches', TObject(PtrInt(ord(suInches)))); +end; + +function TRowHeightForm.GetRowHeight: Single; +begin + Result := EdRowHeight.Value; +end; + +function TRowHeightForm.GetRowHeightType: TsRowHeightType; +begin + if RbDefault.Checked then + Result := rhtDefault + else if RbAuto.Checked then + Result := rhtAuto + else + Result := rhtCustom; +end; + +function TRowHeightForm.GetUnits: TsSizeUnits; +begin + if CbUnits.ItemIndex = -1 then + Result := FWorkbook.Units else + Result := TsSizeUnits(IntPtr(CbUnits.Items.Objects[CbUnits.ItemIndex])); +end; + +procedure TRowHeightForm.RowHeightTypeChanged(Sender: TObject); +begin + LblRowHeight.Enabled := RbCustom.Checked; + EdRowHeight.Enabled := RbCustom.Checked; + CbUnits.Enabled := RbCustom.Checked; +end; + +procedure TRowHeightForm.SetData(AWorkbook: TsWorkbook; ARowHeight: Single; + ARowHeightType: TsRowHeightType); +begin + SetWorkbook(AWorkbook); + SetRowHeight(ARowHeight); + SetUnits(AWorkbook.Units); + SetRowHeightType(ARowHeightType); +end; + +procedure TRowHeightForm.SetRowHeight(AValue: Single); +begin + EdRowHeight.Value := AValue; +end; + +procedure TRowHeightForm.SetRowHeightType(AValue: TsRowHeightType); +begin + RbDefault.Checked := AValue = rhtDefault; + RbAuto.Checked := AValue= rhtAuto; + RbCustom.Checked := AValue = rhtCustom; + RowHeightTypeChanged(nil); +end; + +procedure TRowHeightForm.SetUnits(AValue: TsSizeUnits); +var + i: Integer; +begin + FOldUnits := GetUnits; + for i:=0 to CbUnits.Items.Count-1 do + if TsSizeUnits(IntPtr(CbUnits.Items.Objects[i])) = AValue then + begin + CbUnits.ItemIndex := i; + exit; + end; +end; + +procedure TRowHeightForm.SetWorkbook(AValue: TsWorkbook); +begin + FWorkbook := AValue; + FOldUnits := FWorkbook.Units; +end; + +end. + diff --git a/applications/spready/ssearchform.lfm b/applications/spready/ssearchform.lfm new file mode 100644 index 000000000..63bc78d82 --- /dev/null +++ b/applications/spready/ssearchform.lfm @@ -0,0 +1,309 @@ +object SearchForm: TSearchForm + Left = 238 + Height = 341 + Top = 157 + Width = 487 + BorderStyle = bsDialog + Caption = 'Search' + ClientHeight = 341 + ClientWidth = 487 + FormStyle = fsStayOnTop + OnClose = FormClose + OnCreate = FormCreate + OnShow = FormShow + LCLVersion = '1.5' + object ButtonPanel: TPanel + Left = 0 + Height = 38 + Top = 303 + Width = 487 + Align = alBottom + BevelOuter = bvNone + ClientHeight = 38 + ClientWidth = 487 + TabOrder = 0 + object Bevel1: TBevel + Left = 6 + Height = 3 + Top = 0 + Width = 475 + Align = alTop + BorderSpacing.Left = 6 + BorderSpacing.Right = 6 + Shape = bsTopLine + end + object BtnSearchBack: TBitBtn + Left = 244 + Height = 25 + Top = 7 + Width = 75 + Anchors = [akTop, akRight] + Caption = 'Previous' + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 000000000000000000000000000000000000994E035C994E0399000000000000 + 0000000000000000000000000000000000000000000000000000000000002E2E + 2E2A141414840505055C000000009E53075C9D5206CC9D5206CC000000000000 + 0000000000000000000000000000000000000000000000000000000000003737 + 3774EADADAFF433F3F9E713E0987A3580BCCFFBA16FFA3580BCC000000000000 + 0000000000000000000000000000000000000000000000000000000000003E3E + 3E4B64606090CAA88BFF9A5813EAF7BA30FFF6B11DFFAA5F10CC000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000915B2180A6631CE7ECB952FFE09E29FFE5A83AFFB16616CC000000000000 + 000000000000000000000000000000000000000000000000000000000000BA6F + 1D5CB96E1CCCE9BD6EFFCF9240FFCF9240FFD9A352FFB26A1BD4040404560404 + 047904040487040404790404045604040416000000000000000000000000C277 + 22CCFAD589FFE9AD61FFDFA357FFD5994DFFDCA95DFFB06D22E79D9791A5EEE8 + E3C4F9F3EDD6EFEAE5C5A3A09EA92928287D1111112A0000000000000000C97E + 275CCA7F28CCFBD88CFFEEB266FFEEB266FFF4C276FFCD8B40F2F3E6D9CBF6ED + E4CEF6EDE4CEF6EDE4CEF7EFE6D1DFD9D3B83D3C3B7426262614000000000000 + 0000D1862D5CD2872ECCFDDD91FFF2B96DFFF7CA7EFFD59345F3F5E9DFCBF6ED + E4CEF6EDE4CEF6EDE4CEF6EDE4CEF6ECE2CEADA69E9D31313149000000000000 + 000000000000D88D335CD98E33CCFEE195FFFBD488FFDB9848F2F6EDE4CEF6ED + E4CEF6EDE4CEF6EDE4CEF6EDE4CEF6EDE4CEE7D8CAB838383865000000000000 + 00000000000000000000DF94385CD08C38E2FFE498FFE19E4CF2E8D2BBC0F6ED + E4CEF6EDE4CEF6EDE4CEF6EDE4CEF6EDE4CEEDDBC8C53E3E3E6F000000000000 + 0000000000000000000000000000A4773E99E4A14DEEE5A24FF2E8D2BBC0E8D2 + BBC0E8D2BBC0E8D2BBC0E8D2BBC0E8D2BBC0E4D3C1B243434360000000000000 + 000000000000000000000000000049494943CB9E68B7E8AF69E6F1E3D5C8F6ED + E4CEF6EDE4CEF6EDE4CEF6EDE4CEF2E4D6C8B0A4979149494943000000000000 + 00000000000000000000000000004D4D4D115F5D5A64D5C1AEA1EBD8C4C2F6EC + E2CDF6EDE4CEF6EDE4CEF6ECE2CDD9C8B8A4605D5B644D4D4D11000000000000 + 0000000000000000000000000000000000005151512163605E62B1A3948BE6D5 + C5AFF4EADFC7EDE3D9B5B6ACA28E63605E625151512100000000000000000000 + 0000000000000000000000000000000000000000000054545411555555405555 + 555A555555655555555A55555540545454110000000000000000 + } + OnClick = ExecuteClick + TabOrder = 0 + Visible = False + end + object BtnClose: TBitBtn + Left = 404 + Height = 25 + Top = 7 + Width = 75 + Anchors = [akTop, akRight] + Cancel = True + DefaultCaption = True + Kind = bkClose + ModalResult = 11 + TabOrder = 1 + end + object BtnSearch: TBitBtn + Left = 324 + Height = 25 + Top = 7 + Width = 75 + Anchors = [akTop, akRight] + Caption = 'Search' + Default = True + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000994E0399994E + 035C000000000000000000000000000000000000000000000000000000002E2E + 2E2A141414840505055C000000000000000000000000000000009D5206CC9D52 + 06CC9E53075C0000000000000000000000000000000000000000000000003737 + 3774EADADAFF433F3F9E05050544000000000000000000000000A3580BCCFFBF + 25FFA3580BCCA4590C5C00000000000000000000000000000000000000003E3E + 3E4B64606090DDD1D1FF302E2E96040404330000000000000000AA5F10CCFBB8 + 21FFFBBF34FFAA5F10CCAB60115C000000000000000000000000000000000000 + 00003D3D3D3853515186CCC4C4FF2221218C0404042500000000B16616CCEFB3 + 39FFEAA41DFFF2BD4AFFB16616CCB267175C0000000000000000000000000000 + 0000000000003C3C3C2A4746467CBCB8B8FF161515830404042AAB651ADDE4AE + 50FFD99934FFD99934FFEABB60FFB56B1BD0BA6F1D5C00000000000000000000 + 000000000000000000003B3B3B1F3C3C3C73AFADADFF2B292887BC7B31EDE5B4 + 66FFCE9244FFCD9143FFCD9143FFE7BC6FFFBB7321D400000000000000000000 + 0000000000000000000000000000373737244746447BDED1C4BED09045F5F5C6 + 7AFFE9AD61FFDFA357FFF1CC80FFCD8C42F18A602FA626262614000000000000 + 000000000000000000000000000031313149A89D9397EAD5BFC3D7974BF5F7CB + 7FFFF1B66AFFFDDC90FFD8984CF5E6C297E0ADA69E9D31313149000000000000 + 000000000000000000000000000038383865E1CFBCB1E8D2BBC0DD9D50F5FBD4 + 88FFFFE397FFDD9D50F5E9C59BE0F6EDE4CEE7D8CAB838383865000000000000 + 00000000000000000000000000003E3E3E6FE9D4BEBEE8D2BBC0E19E4CF2FFE5 + 99FFE3A354F5ECC89DE0F6EDE4CEF6EDE4CEEDDBC8C53E3E3E6F000000000000 + 000000000000000000000000000043434360E0CBB6ACE8D2BBC0E5A24FF2E5A2 + 4FF2E6BA84D7E8D2BBC0E8D2BBC0E8D2BBC0E4D3C1B243434360000000000000 + 000000000000000000000000000049494943AD9F918EE8D2BBC0EBB573E9F0CC + A0E0F6EDE4CEF6EDE4CEF6EDE4CEF2E4D6C8B0A4979149494943000000000000 + 00000000000000000000000000004D4D4D115F5D5A64D5C1AEA1EBD8C4C2F6EC + E2CDF6EDE4CEF6EDE4CEF6ECE2CDD9C8B8A4605D5B644D4D4D11000000000000 + 0000000000000000000000000000000000005151512163605E62B1A3948BE6D5 + C5AFF4EADFC7EDE3D9B5B6ACA28E63605E625151512100000000000000000000 + 0000000000000000000000000000000000000000000054545411555555405555 + 555A555555655555555A55555540545454110000000000000000 + } + OnClick = ExecuteClick + TabOrder = 2 + end + end + object TabControl: TTabControl + Left = 8 + Height = 287 + Top = 8 + Width = 471 + OnChange = TabControlChange + OnChanging = TabControlChanging + TabIndex = 0 + Tabs.Strings = ( + 'Search' + 'Replace' + ) + Align = alClient + BorderSpacing.Around = 8 + TabOrder = 1 + object SearchTextPanel: TPanel + Left = 2 + Height = 33 + Top = 23 + Width = 467 + Align = alTop + BevelOuter = bvNone + ClientHeight = 33 + ClientWidth = 467 + ParentColor = False + TabOrder = 1 + object LblSearchText: TLabel + Left = 14 + Height = 15 + Top = 12 + Width = 53 + Caption = 'Search for' + ParentColor = False + end + object CbSearchText: TComboBox + Left = 104 + Height = 23 + Top = 8 + Width = 351 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + TabOrder = 0 + end + end + object ReplaceTextPanel: TPanel + Left = 2 + Height = 33 + Top = 56 + Width = 467 + Align = alTop + BevelOuter = bvNone + ClientHeight = 33 + ClientWidth = 467 + ParentColor = False + TabOrder = 2 + Visible = False + object LblSearchText1: TLabel + Left = 14 + Height = 15 + Top = 12 + Width = 67 + Caption = 'Replace with' + ParentColor = False + end + object CbReplaceText: TComboBox + Left = 104 + Height = 23 + Top = 8 + Width = 351 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + TabOrder = 0 + end + end + object SearchParamsPanel: TPanel + Left = 2 + Height = 196 + Top = 89 + Width = 467 + Align = alClient + BevelOuter = bvNone + ClientHeight = 196 + ClientWidth = 467 + ParentColor = False + TabOrder = 3 + object CgOptions: TCheckGroup + Left = 16 + Height = 163 + Top = 16 + Width = 192 + AutoFill = True + Caption = 'Options' + ChildSizing.LeftRightSpacing = 6 + ChildSizing.TopBottomSpacing = 6 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.EnlargeVertical = crsHomogenousChildResize + ChildSizing.ShrinkHorizontal = crsScaleChilds + ChildSizing.ShrinkVertical = crsScaleChilds + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 1 + ClientHeight = 143 + ClientWidth = 188 + Items.Strings = ( + 'Compare entire cell ' + 'Match case' + 'Regular expression' + 'Search along rows' + 'Continue at start/end' + ) + TabOrder = 0 + Data = { + 050000000202020202 + } + end + object RgSearchWithin: TRadioGroup + Left = 232 + Height = 67 + Top = 16 + Width = 223 + AutoFill = True + Caption = 'Search within' + ChildSizing.LeftRightSpacing = 6 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.EnlargeVertical = crsHomogenousChildResize + ChildSizing.ShrinkHorizontal = crsScaleChilds + ChildSizing.ShrinkVertical = crsScaleChilds + ChildSizing.Layout = cclTopToBottomThenLeftToRight + ChildSizing.ControlsPerLine = 2 + ClientHeight = 47 + ClientWidth = 219 + ColumnLayout = clVerticalThenHorizontal + Columns = 2 + ItemIndex = 0 + Items.Strings = ( + 'workbook' + 'worksheet' + 'column' + 'row' + ) + TabOrder = 1 + end + object RgSearchStart: TRadioGroup + Left = 232 + Height = 56 + Top = 123 + Width = 223 + AutoFill = True + Caption = 'Start search at' + ChildSizing.LeftRightSpacing = 6 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.EnlargeVertical = crsHomogenousChildResize + ChildSizing.ShrinkHorizontal = crsScaleChilds + ChildSizing.ShrinkVertical = crsScaleChilds + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 2 + ClientHeight = 36 + ClientWidth = 219 + Columns = 2 + ItemIndex = 0 + Items.Strings = ( + 'active cell' + 'beginning/end' + ) + TabOrder = 2 + end + end + end +end diff --git a/applications/spready/ssearchform.pas b/applications/spready/ssearchform.pas new file mode 100644 index 000000000..11aa2cdad --- /dev/null +++ b/applications/spready/ssearchform.pas @@ -0,0 +1,372 @@ +unit sSearchForm; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, + StdCtrls, ExtCtrls, Buttons, ComCtrls, fpsTypes, fpspreadsheet, fpsSearch; + +type + TsSearchEvent = procedure (Sender: TObject; AFound: Boolean; + AWorksheet: TsWorksheet; ARow, ACol: Cardinal) of object; + + { TSearchForm } + + TSearchForm = class(TForm) + Bevel1: TBevel; + BtnSearchBack: TBitBtn; + BtnClose: TBitBtn; + BtnSearch: TBitBtn; + CbSearchText: TComboBox; + CbReplaceText: TComboBox; + CgOptions: TCheckGroup; + LblSearchText: TLabel; + ButtonPanel: TPanel; + LblSearchText1: TLabel; + SearchParamsPanel: TPanel; + SearchTextPanel: TPanel; + RgSearchStart: TRadioGroup; + RgSearchWithin: TRadioGroup; + ReplaceTextPanel: TPanel; + TabControl: TTabControl; + procedure ExecuteClick(Sender: TObject); + procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure TabControlChange(Sender: TObject); + procedure TabControlChanging(Sender: TObject; var AllowChange: Boolean); + private + { private declarations } + FSearchEngine: TsSearchEngine; + FWorkbook: TsWorkbook; + FFoundWorksheet: TsWorksheet; + FFoundRow, FFoundCol: Cardinal; + FSearchParams: TsSearchParams; + FReplaceParams: TsReplaceParams; + FOnFound: TsSearchEvent; + function GetReplaceParams: TsReplaceParams; + function GetSearchParams: TsSearchParams; + procedure SetReplaceParams(const AValue: TsReplaceParams); + procedure SetSearchParams(const AValue: TsSearchParams); + protected + procedure ConfirmReplacementHandler(Sender: TObject; AWorksheet: TsWorksheet; + ARow, ACol: Cardinal; const ASearchText, AReplaceText: String; + var AConfirmReplacement: TsConfirmReplacementResult); + procedure PopulateOptions; + public + { public declarations } + procedure Execute(AWorkbook: TsWorkbook); + property Workbook: TsWorkbook read FWorkbook; + property SearchParams: TsSearchParams read GetSearchParams write SetSearchParams; + property ReplaceParams: TsReplaceParams read GetReplaceParams write SetReplaceParams; + property OnFound: TsSearchEvent read FOnFound write FOnFound; + end; + +var + SearchForm: TSearchForm; + + DefaultSearchParams: TsSearchParams = ( + SearchText: ''; + Options: []; + Within: swWorksheet + ); + DefaultReplaceParams: TsReplaceParams = ( + ReplaceText: ''; + Options: [roConfirm] + ); + + +implementation + +{$R *.lfm} + +uses + fpsUtils; + +const + MAX_SEARCH_ITEMS = 10; + + // Search & replace + COMPARE_ENTIRE_CELL = 0; + MATCH_CASE = 1; + REGULAR_EXPRESSION = 2; + SEARCH_ALONG_ROWS = 3; + CONTINUE_AT_START_END = 4; + // Replace only + REPLACE_ENTIRE_CELL = 5; + REPLACE_ALL = 6; + CONFIRM_REPLACEMENT = 7; + + BASE_HEIGHT = 340; // Design height of SearchForm + + SEARCH_TAB = 0; + REPLACE_TAB = 1; + +var + CONFIRM_REPLACEMENT_DLG_X: Integer = -1; + CONFIRM_REPLACEMENT_DLG_Y: Integer = -1; + +{ TSearchForms } + +procedure TSearchForm.ConfirmReplacementHandler(Sender: TObject; + AWorksheet: TsWorksheet; ARow, ACol: Cardinal; const ASearchText, AReplaceText: String; + var AConfirmReplacement: TsConfirmReplacementResult); +var + F: TForm; +begin + Unused(AWorksheet, ARow, ACol); + Unused(ASearchText, AReplaceText); + F := CreateMessageDialog('Replace?', mtConfirmation, [mbYes, mbNo, mbCancel]); + try + if (CONFIRM_REPLACEMENT_DLG_X = -1) then + F.Position := poMainformCenter + else begin + F.Position := poDesigned; + F.Left := CONFIRM_REPLACEMENT_DLG_X; + F.Top := CONFIRM_REPLACEMENT_DLG_Y; + end; + case F.ShowModal of + mrYes: AConfirmReplacement := crReplace; + mrNo : AConfirmReplacement := crIgnore; + mrCancel: AConfirmReplacement := crAbort; + end; + CONFIRM_REPLACEMENT_DLG_X := F.Left; + CONFIRM_REPLACEMENT_DLG_Y := F.Top; + finally + F.Free; + end; + { + case MessageDlg('Replace?', mtConfirmation, [mbYes, mbNo, mbCancel], 0) of + mrYes: AConfirmReplacement := crReplace; + mrNo : AConfirmReplacement := crIgnore; + mrCancel: AConfirmReplacement := crAbort; + end; + } +end; + +procedure TSearchForm.Execute(AWorkbook: TsWorkbook); +begin + FWorkbook := AWorkbook; + Show; +end; + +procedure TSearchForm.ExecuteClick(Sender: TObject); +var + sp: TsSearchParams; + rp: TsReplaceParams; + found: Boolean; + crs: TCursor; +begin + sp := GetSearchParams; + if sp.SearchText = '' then + exit; + + if TabControl.TabIndex = REPLACE_TAB then + rp := GetReplaceParams; + + if CbSearchText.Items.IndexOf(sp.SearchText) = -1 then + begin + CbSearchText.Items.Insert(0, sp.SearchText); + while CbSearchText.Items.Count > MAX_SEARCH_ITEMS do + CbSearchText.Items.Delete(CbSearchText.Items.Count-1); + end; + + if (TabControl.TabIndex = REPLACE_TAB) and + (CbReplaceText.Items.IndexOf(rp.ReplaceText) = -1) then + begin + CbReplaceText.items.Insert(0, rp.ReplaceText); + while CbReplaceText.Items.Count > MAX_SEARCH_ITEMS do + CbReplaceText.Items.Delete(CbReplaceText.Items.Count-1); + end; + + crs := Screen.Cursor; + try + Screen.Cursor := crHourglass; + if FSearchEngine = nil then + begin + FSearchEngine := TsSearchEngine.Create(FWorkbook); + FSearchEngine.OnConfirmReplacement := @ConfirmReplacementHandler; + if (soBackward in sp.Options) then + Include(sp.Options, soBackward) else + Exclude(sp.Options, soBackward); + case Tabcontrol.TabIndex of + 0: found := FSearchEngine.FindFirst(sp, FFoundWorksheet, FFoundRow, FFoundCol); + 1: found := FSearchEngine.ReplaceFirst(sp, rp, FFoundWorksheet, FFoundRow, FFoundCol); + end; + end else + begin + // Adjust "backward" option according to the button clicked + if (Sender = BtnSearchBack) then + Include(sp.Options, soBackward) else + Exclude(sp.Options, soBackward); + // Begin searching at current position + Exclude(sp.Options, soEntireDocument); + // User may select a different worksheet/different cell to continue search! + FFoundWorksheet := FWorkbook.ActiveWorksheet; + FFoundRow := FFoundWorksheet.ActiveCellRow; + FFoundCol := FFoundWorksheet.ActiveCellCol; + case TabControl.TabIndex of + 0: found := FSearchEngine.FindFirst(sp, FFoundWorksheet, FFoundRow, FFoundCol); + 1: found := FSearchEngine.ReplaceFirst(sp, rp, FFoundWorksheet, FFoundRow, FFoundCol); + end; + end; + + finally + Screen.Cursor := crs; + end; + + if Assigned(FOnFound) then + FOnFound(self, found, FFoundWorksheet, FFoundRow, FFoundCol); + + BtnSearchBack.Visible := true; + BtnSearch.Caption := 'Next'; +end; + +procedure TSearchForm.FormClose(Sender: TObject; var CloseAction: TCloseAction); +var + P: TPoint; +begin + Unused(CloseAction); + FreeAndNil(FSearchEngine); + P.X := Left; + P.Y := Top; + Position := poDesigned; + Left := P.X; + Top := P.Y; +end; + +procedure TSearchForm.FormCreate(Sender: TObject); +begin + {$IFDEF MSWINDOWS} + SearchTextPanel.Color := clNone; + ReplaceTextPanel.Color := clNone; + SearchParamsPanel.Color := clNone; + {$ENDIF} + Position := poMainFormCenter; + PopulateOptions; +end; + +procedure TSearchForm.FormShow(Sender: TObject); +begin + BtnSearch.Caption := 'Search'; + BtnSearchBack.Visible := false; + + FFoundCol := UNASSIGNED_ROW_COL_INDEX; + FFoundRow := UNASSIGNED_ROW_COL_INDEX; + FFoundWorksheet := nil; +end; + +function TSearchForm.GetReplaceParams: TsReplaceParams; +begin + if TabControl.TabIndex = 0 then + Result := FReplaceParams + else + begin + Result.ReplaceText := CbReplaceText.Text; + Result.Options := []; + if CgOptions.Checked[REPLACE_ENTIRE_CELL] then + Include(Result.Options, roReplaceEntireCell); + if CgOptions.Checked[REPLACE_ALL] then + Include(Result.Options, roReplaceAll); + if CgOptions.Checked[CONFIRM_REPLACEMENT] then + Include(Result.Options, roConfirm); + FReplaceParams := Result; + end; +end; + +function TSearchForm.GetSearchParams: TsSearchParams; +begin + Result.SearchText := CbSearchText.Text; + Result.Options := []; + if CgOptions.Checked[COMPARE_ENTIRE_CELL] then + Include(Result.Options, soCompareEntireCell); + if CgOptions.Checked[MATCH_CASE] then + Include(Result.Options, soMatchCase); + if CgOptions.Checked[REGULAR_EXPRESSION] then + Include(Result.Options, soRegularExpr); + if CgOptions.Checked[SEARCH_ALONG_ROWS] then + Include(Result.Options, soAlongRows); + if CgOptions.Checked[CONTINUE_AT_START_END] then + Include(Result.Options, soWrapDocument); + if RgSearchStart.ItemIndex = 1 then + Include(Result.Options, soEntireDocument); + Result.Within := TsSearchWithin(RgSearchWithin.ItemIndex); +end; + +procedure TSearchForm.PopulateOptions; +begin + with CgOptions.Items do + begin + Clear; + Add('Compare entire cell'); + Add('Match case'); + Add('Regular expression'); + Add('Search along rows'); + Add('Continue at start/end'); + if TabControl.TabIndex = REPLACE_TAB then + begin + Add('Replace entire cell'); + Add('Replace all'); + Add('Confirm replacement'); + end; + end; +end; + +procedure TSearchForm.SetSearchParams(const AValue: TsSearchParams); +begin + CbSearchText.Text := Avalue.SearchText; + CgOptions.Checked[COMPARE_ENTIRE_CELL] := (soCompareEntireCell in AValue.Options); + CgOptions.Checked[MATCH_CASE] := (soMatchCase in AValue.Options); + CgOptions.Checked[REGULAR_EXPRESSION] := (soRegularExpr in Avalue.Options); + CgOptions.Checked[SEARCH_ALONG_ROWS] := (soAlongRows in AValue.Options); + CgOptions.Checked[CONTINUE_AT_START_END] := (soWrapDocument in Avalue.Options); + RgSearchWithin.ItemIndex := ord(AValue.Within); + RgSearchStart.ItemIndex := ord(soEntireDocument in AValue.Options); +end; + +procedure TSearchForm.SetReplaceParams(const AValue: TsReplaceParams); +begin + FReplaceParams := AValue; + if TabControl.TabIndex = REPLACE_TAB then + begin + CbReplaceText.Text := AValue.ReplaceText; + CgOptions.Checked[REPLACE_ENTIRE_CELL] := (roReplaceEntireCell in AValue.Options); + CgOptions.Checked[REPLACE_ALL] := (roReplaceAll in AValue.Options); + CgOptions.Checked[CONFIRM_REPLACEMENT] := (roConfirm in AValue.Options); + end; +end; + +procedure TSearchForm.TabControlChange(Sender: TObject); +var + h, d: Integer; +begin + ReplaceTextPanel.Visible := (TabControl.TabIndex = REPLACE_TAB); + PopulateOptions; + SetSearchParams(FSearchParams); + SetReplaceParams(FReplaceParams); + h := RgSearchStart.Top + RgSearchStart.Height - CgOptions.Top; + if TabControl.TabIndex = 0 then + begin + CgOptions.Height := h; + Height := BASE_HEIGHT - ReplaceTextPanel.Height; + end else + begin + d := 3 * 16; + CgOptions.Height := h + d; + Height := BASE_HEIGHT + d; + end; +end; + +procedure TSearchForm.TabControlChanging(Sender: TObject; + var AllowChange: Boolean); +begin + AllowChange := true; + FSearchParams := GetSearchParams; + FReplaceParams := GetReplaceParams; +end; + + +end. + diff --git a/applications/spready/ssortparamsform.lfm b/applications/spready/ssortparamsform.lfm new file mode 100644 index 000000000..04de28be6 --- /dev/null +++ b/applications/spready/ssortparamsform.lfm @@ -0,0 +1,218 @@ +object SortParamsForm: TSortParamsForm + Left = 434 + Height = 314 + Top = 274 + Width = 496 + Caption = 'Sorting criteria' + ClientHeight = 314 + ClientWidth = 496 + OnCreate = FormCreate + LCLVersion = '1.7' + object ButtonPanel: TButtonPanel + Left = 6 + Height = 34 + Top = 274 + Width = 484 + OKButton.Name = 'OKButton' + OKButton.DefaultCaption = True + OKButton.OnClick = OKButtonClick + HelpButton.Name = 'HelpButton' + HelpButton.DefaultCaption = True + CloseButton.Name = 'CloseButton' + CloseButton.DefaultCaption = True + CancelButton.Name = 'CancelButton' + CancelButton.DefaultCaption = True + TabOrder = 0 + ShowButtons = [pbOK, pbCancel] + end + object Grid: TStringGrid + Left = 0 + Height = 226 + Top = 42 + Width = 496 + Align = alClient + ColCount = 4 + Columns = < + item + ButtonStyle = cbsPickList + Title.Caption = 'Column' + Width = 120 + end + item + ButtonStyle = cbsCheckboxColumn + PickList.Strings = ( + 'ascending' + 'descending' + ) + Title.Alignment = taCenter + Title.Caption = 'Descending' + Width = 120 + end + item + ButtonStyle = cbsCheckboxColumn + Title.Alignment = taCenter + Title.Caption = 'Ignore case' + Width = 120 + end> + DefaultColWidth = 120 + Options = [goFixedVertLine, goFixedHorzLine, goHorzLine, goRangeSelect, goEditing, goAlwaysShowEditor, goSmoothScroll] + RowCount = 2 + TabOrder = 1 + TitleStyle = tsNative + OnSelectEditor = GridSelectEditor + Cells = ( + 1 + 0 + 1 + 'Sort by' + ) + end + object TopPanel: TPanel + Left = 0 + Height = 42 + Top = 0 + Width = 496 + Align = alTop + BevelOuter = bvNone + ClientHeight = 42 + ClientWidth = 496 + TabOrder = 2 + object BtnAdd: TBitBtn + AnchorSideTop.Control = TopPanel + AnchorSideTop.Side = asrCenter + Left = 7 + Height = 30 + Top = 6 + Width = 83 + Caption = 'Add' + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0041924E233D8F497D3A8C44DB368940F332873CF32F84 + 37DB2C81337D287F3023FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0049995853459653E6419950FF7DC28FFF96D0A6FF96CFA6FF78BE + 89FF368D42FF2C8134E6297F3053FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00519F61534D9C5DF464B478FFA8DBB5FF87CC98FF66BC7DFF64BA7CFF86CB + 98FFA5D9B4FF58AA6BFF2C8134F4297F3053FFFFFF00FFFFFF00FFFFFF0059A6 + 6B2256A366E56AB97DFFA8DBB2FF60BC77FF5CBA73FF59B870FF59B56FFF58B5 + 6FFF5BB774FFA5D9B3FF5AAA6CFF2C8234E5297F3022FFFFFF00FFFFFF005DA9 + 707E53AB68FFAADDB4FF64C179FF5FBE71FF60BC77FFFFFFFFFFFFFFFFFF59B8 + 70FF58B56EFF5CB774FFA6DAB4FF388F43FF2C82347EFFFFFF00FFFFFF0061AC + 75DB8ACC98FF89D396FF6BC67AFF63C170FF55AB65FFFFFFFFFFFFFFFFFF59B8 + 70FF59B870FF5BB972FF85CC97FF7BBE8DFF308539DBFFFFFF00FFFFFF0065AF + 7AF6A9DDB3FF7DCF8AFF75CC81FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF67BE7DFF9CD4ABFF34883DF6FFFFFF00FFFFFF0069B2 + 7EF6B6E2BEFF8BD597FF7AC986FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF69C17EFF9DD4AAFF388B42F6FFFFFF00FFFFFF006DB5 + 83DBACDDB6FFA6DFAFFF81CB8CFF7CC986FF6EBD79FFFFFFFFFFFFFFFFFF5BAC + 6AFF60BC77FF5CBA73FF8BD199FF80C592FF3C8E47DBFFFFFF00FFFFFF0070B8 + 877E85C797FFD2EED7FF95D9A0FF8AD394FF7FC889FFFFFFFFFFFFFFFFFF79CD + 85FF6BC37CFF6FC77EFFACDFB5FF459E57FF40914C7EFFFFFF00FFFFFF0073BA + 8A2270B887E5AADAB7FFD8F1DCFF92D89DFF88CD93FF84CC8EFF8BD496FF8AD4 + 95FF83D28EFFAFE0B7FF6BB97DFF489856E544945122FFFFFF00FFFFFF00FFFF + FF0073BB8B5370B887F4AFDCBBFFDCF2E0FFB6E4BDFF9BDBA5FF96D9A0FFA5DF + AFFFC0E8C5FF79C28AFF509E5FF44C9B5B53FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0073BB8B5371B887E694CEA4FFC3E6CBFFCFEBD4FFC9E9CEFFAFDD + B8FF6DB97FFF58A569E654A16553FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0074BB8B2371B9887D6EB684DB6AB380F367B17CF363AE + 77DB60AB737D5CA86E23FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = BtnAddClick + TabOrder = 0 + end + object BtnDelete: TBitBtn + AnchorSideLeft.Control = BtnAdd + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = BtnAdd + Left = 96 + Height = 30 + Top = 6 + Width = 83 + BorderSpacing.Left = 6 + Caption = 'Delete' + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF003F54C3233A50C27D3853BEDB3551BDF3304BBCF32E4E + B8DB2B4CB77D2748B523FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF004658C8534255C6E63C52CCFF757AE8FF8F92EEFF8F92EEFF7178 + E4FF334DC1FF2B4AB7E6294BB553FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF004D5ACD534959CBF45C65E0FFA1A6F5FF7E86EFFF5B63E9FF595DE7FF7D84 + EEFF9EA0F4FF515DD7FF2B4AB7F4294BB553FFFFFF00FFFFFF00FFFFFF00545F + D2225361CFE5616BE3FFA1ACF5FF545FECFF505CEAFF4D59E9FF4E59E6FF4C56 + E6FF5056E6FF9EA2F4FF5460D6FF2A4AB8E5294BB522FFFFFF00FFFFFF005860 + D47E4B56DBFFA2ABF6FF5664F0FF5266EEFF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4C58E6FF525AE6FF9FA3F5FF3450C4FF2A4AB87EFFFFFF00FFFFFF005C62 + D7DB818CEEFF7E91F7FF5D73F3FF4D59E9FF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4D59E9FF4F5BE9FF7B83F0FF757BE2FF2E4BBADBFFFFFF00FFFFFF005F63 + DAF6A1ABF7FF7086F8FF6882F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5C66EAFF969CF1FF3250BCF6FFFFFF00FFFFFF006469 + DBF6AFB9F9FF7F93FAFF7085F0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5E6AEEFF969DF1FF364FBEF6FFFFFF00FFFFFF00676A + DEDBA5AFF5FF9DABFAFF778CF0FF545FECFF545FECFF545FECFF545FECFF545F + ECFF545FECFF6377F2FF818EF4FF787FE9FF3A53C0DBFFFFFF00FFFFFF006A69 + E07E7D83EAFFCDD4FCFF8B9DFAFF7E93F7FF758AEEFF6C84F6FF6C84F6FF6C84 + F6FF6C84F6FF6379F3FFA4AFF8FF3E4FD0FF3E54C27EFFFFFF00FFFFFF006C6C + E1226A69E0E5A3A7F3FFD4DBFDFF879AFAFF7F91F0FF7A8EF1FF7F94F8FF7E92 + F9FF768CF8FFA8B6F8FF636EE3FF4557C7E54156C522FFFFFF00FFFFFF00FFFF + FF006D6CE3536A69E0F4AAADF2FFD8DCFDFFAEBAFAFF91A3FAFF8B9DFAFF9CA9 + FBFFBAC7FCFF707BE9FF4C5BCCF44858CA53FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF006D6CE3536A6ADFE68E93EDFFBEC3F8FFCCD3F9FFC4CBF9FFAAB4 + F4FF6670E2FF535ED1E6505DCE53FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF006D6DE2236B6AE17D686ADDDB6364DCF36164DAF35D63 + D9DB5B63D67D5862D423FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = BtnDeleteClick + TabOrder = 1 + end + object CbSortColsRows: TComboBox + AnchorSideLeft.Control = BtnDelete + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = BtnAdd + AnchorSideTop.Side = asrCenter + Left = 187 + Height = 23 + Top = 10 + Width = 160 + BorderSpacing.Left = 8 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'Sort top to bottom' + 'Sort left to right' + ) + OnChange = CbSortColsRowsChange + Style = csDropDownList + TabOrder = 2 + Text = 'Sort top to bottom' + end + object CbPriority: TComboBox + AnchorSideLeft.Control = CbSortColsRows + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = BtnAdd + AnchorSideTop.Side = asrCenter + Left = 355 + Height = 23 + Top = 10 + Width = 120 + BorderSpacing.Left = 8 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'Numbers first' + 'Text first' + ) + Style = csDropDownList + TabOrder = 3 + Text = 'Numbers first' + end + end +end diff --git a/applications/spready/ssortparamsform.pas b/applications/spready/ssortparamsform.pas new file mode 100644 index 000000000..0a252eea3 --- /dev/null +++ b/applications/spready/ssortparamsform.pas @@ -0,0 +1,268 @@ +unit sSortParamsForm; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, + ButtonPanel, Grids, ExtCtrls, Buttons, StdCtrls, + fpstypes, fpspreadsheetgrid; + +type + + { TSortParamsForm } + + TSortParamsForm = class(TForm) + BtnAdd: TBitBtn; + BtnDelete: TBitBtn; + ButtonPanel: TButtonPanel; + CbSortColsRows: TComboBox; + CbPriority: TComboBox; + TopPanel: TPanel; + Grid: TStringGrid; + procedure BtnAddClick(Sender: TObject); + procedure BtnDeleteClick(Sender: TObject); + procedure CbSortColsRowsChange(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure GridSelectEditor(Sender: TObject; aCol, aRow: Integer; + var Editor: TWinControl); + procedure OKButtonClick(Sender: TObject); + private + { private declarations } + FWorksheetGrid: TsWorksheetGrid; + function GetSortParams: TsSortParams; + procedure SetWorksheetGrid(AValue: TsWorksheetGrid); + procedure UpdateColRowList; + procedure UpdateCmds; + function ValidParams(out AMsg: String): Boolean; + public + { public declarations } + property SortParams: TsSortParams read GetSortParams; + property WorksheetGrid: TsWorksheetGrid read FWorksheetGrid write SetWorksheetGrid; + end; + +var + SortParamsForm: TSortParamsForm; + +implementation + +{$R *.lfm} + +uses + fpsutils; + +procedure TSortParamsForm.CbSortColsRowsChange(Sender: TObject); +begin + UpdateColRowList; + UpdateCmds; +end; + +procedure TSortParamsForm.FormCreate(Sender: TObject); +begin + {$IFDEF WINDOWS} + if Win32MajorVersion >= 10 then begin + // avoid the ugly themed grid of Win10... + Grid.TitleStyle := tsLazarus; + end; + {$ENDIF} +end; + +procedure TSortParamsForm.GridSelectEditor(Sender: TObject; + aCol, aRow: Integer; var Editor: TWinControl); +begin + Unused(aCol, aRow); + if (Editor is TCustomComboBox) then + (Editor as TCustomComboBox).Style := csDropDownList; +end; + +procedure TSortParamsForm.OKButtonClick(Sender: TObject); +var + msg: String; +begin + if not ValidParams(msg) then begin + MessageDlg(msg, mtError, [mbOK], 0); + ModalResult := mrNone; + end; +end; + +procedure TSortParamsForm.BtnAddClick(Sender: TObject); +var + numConditions: Integer; +begin + case CbSortColsRows.ItemIndex of + 0: numConditions := FWorksheetGrid.Selection.Right - FWorksheetGrid.Selection.Left + 1; + 1: numConditions := FWorksheetGrid.Selection.Bottom - FWorksheetGrid.Selection.Top + 1; + end; + if Grid.RowCount - Grid.FixedRows >= numConditions then + exit; // there can't be more conditions than defined by the worksheetgrid selection + Grid.RowCount := Grid.RowCount + 1; + Grid.Cells[0, Grid.RowCount-1] := 'Then by'; + Grid.Cells[1, Grid.RowCount-1] := ''; + Grid.Cells[2, Grid.RowCount-1] := '0'; + Grid.Cells[3, Grid.RowCount-1] := '0'; + UpdateCmds; +end; + +procedure TSortParamsForm.BtnDeleteClick(Sender: TObject); +begin + if Grid.RowCount = Grid.FixedRows + 1 then + exit; // 1 condition must remain + Grid.DeleteRow(Grid.Row); + Grid.Cells[0, 1] := 'Sort by'; + UpdateCmds; +end; + +function TSortParamsForm.GetSortParams: TsSortParams; +var + i, p: Integer; + n: Cardinal; + sortOptions: TsSortOptions; + s: String; +begin + // Sort by column or rows? + Result := InitSortParams(CbSortColsRows.ItemIndex = 0, 0); + + // Number before Text, or reversed? + Result.Priority := TsSortPriority(CbPriority.ItemIndex); + + for i:=Grid.FixedRows to Grid.RowCount-1 do + begin + sortOptions := []; + + // Sort index column + s := Grid.Cells[1, i]; // the cell text is "Column A" or "Row A" + if s = '' then + raise Exception.Create('[TSortParamsForm.GetSortParams] No sort index selected.'); + // This case should have been detected already by the ValidParams method. + + p := pos(' ', s); // we look for the space and extract column/row index + if p = 0 then + raise Exception.Create('[TSortParamsForm.GetSortParams] Unexpected string in grid.'); + s := copy(s, p+1, Length(s)); + case CbSortColsRows.ItemIndex of + 0: if not ParseCellColString(s, n) then + raise Exception.CreateFmt('[TSortParamsForm.GetSortParams] '+ + 'Unexpected column identifier in row %d', [i]); + 1: if TryStrToInt(s, LongInt(n)) then + dec(n) + else + raise Exception.CreateFmt('[TSortParamsForm.GetSortParams] ' + + 'Unexpected row identifier in row %s', [i]); + end; + + // Sort order column + s := Grid.Cells[2, i]; + if s = '' then + raise Exception.Create('[TSortParamsForm.GetSortParams] No sort direction selected.'); + if s = '1' then + Include(sortOptions, ssoDescending); + + // Case sensitivity column + s := Grid.Cells[3, i]; + if s = '1' then + Include(sortOptions, ssoCaseInsensitive); + + SetLength(Result.Keys, Length(Result.Keys) + 1); + with Result.Keys[Length(Result.Keys)-1] do + begin + Options := sortOptions; + ColRowIndex := n; + end; + end; // for +end; + +procedure TSortParamsForm.SetWorksheetGrid(AValue: TsWorksheetGrid); +begin + FWorksheetGrid := AValue; + UpdateColRowList; + UpdateCmds; + Grid.Cells[1, 1] := Grid.Columns[0].PickList[0]; // Sorting index + Grid.Cells[2, 1] := '0'; // Ascending sort order Grid.Columns[1].CheckedPickList[0]; + Grid.Cells[3, 1] := '0'; // case-sensitive comparisons +end; + +procedure TSortParamsForm.UpdateColRowList; +var + L: TStrings; + r,c: LongInt; + r1,c1, r2,c2: Cardinal; +begin + with FWorksheetGrid do begin + r1 := GetWorksheetRow(Selection.Top); + c1 := GetWorksheetCol(Selection.Left); + r2 := GetWorksheetRow(Selection.Bottom); + c2 := GetWorksheetCol(Selection.Right); + end; + L := TStringList.Create; + try + case CbSortColsRows.ItemIndex of + 0: begin + Grid.RowCount := Grid.FixedRows + 1; + Grid.Columns[0].Title.Caption := 'Columns'; + for c := c1 to c2 do + L.Add('Column ' + GetColString(c)); + end; + 1: begin + Grid.RowCount := Grid.FixedRows + 1; + Grid.Columns[0].Title.Caption := 'Rows'; + for r := r1 to r2 do + L.Add('Row ' + IntToStr(r+1)); + end; + end; + Grid.Columns[0].PickList.Assign(L); + for r := Grid.FixedRows to Grid.RowCount-1 do + begin + Grid.Cells[1, r] := ''; + Grid.Cells[2, r] := '' + end; + finally + L.Free; + end; +end; + +procedure TSortParamsForm.UpdateCmds; +var + r1,c1,r2,c2: Cardinal; + numConditions: Integer; +begin + with FWorksheetGrid do begin + r1 := GetWorksheetRow(Selection.Top); + c1 := GetWorksheetCol(Selection.Left); + r2 := GetWorksheetRow(Selection.Bottom); + c2 := GetWorksheetCol(Selection.Right); + end; + numConditions := Grid.RowCount - Grid.FixedRows; + case CbSortColsRows.ItemIndex of + 0: BtnAdd.Enabled := numConditions < c2-c1+1; + 1: BtnAdd.Enabled := numConditions < r2-r1+1; + end; + BtnDelete.Enabled := numConditions > 1; +end; + +function TSortParamsForm.ValidParams(out AMsg: String): Boolean; +var + i: Integer; +begin + Result := false; + for i:=Grid.FixedRows to Grid.RowCount-1 do + begin + if Grid.Cells[1, i] = '' then + begin + AMsg := Format('No sorting criteria selected in row %d.', [i]); + Grid.SetFocus; + exit; + end; + if Grid.Cells[2, i] = '' then + begin + AMsg := Format('No sort order specified in row %d.', [i]); + Grid.SetFocus; + exit; + end; + end; + Result := true; +end; + + +end. + diff --git a/applications/spready/sutils.pas b/applications/spready/sutils.pas new file mode 100644 index 000000000..628dc27fa --- /dev/null +++ b/applications/spready/sutils.pas @@ -0,0 +1,166 @@ +unit sutils; + +{$mode objfpc}{$H+} + +interface + +uses + fpstypes, fpspreadsheet; + +function GetCellFormatAsString(AWorkbook: TsWorkbook; AIndex: Integer): String; +function GetColorName(AColor: TsColor): String; +function GetFontAsString(AFont: TsFont): String; + + +implementation + +{@@ ---------------------------------------------------------------------------- + Determines the name of a color from its rgb value +-------------------------------------------------------------------------------} +function GetColorName(AColor: TsColor): string; +var + rgba: TRGBA absolute AColor; +begin + case AColor of + scAqua : Result := rsAqua; + scBeige : Result := rsBeige; + scBlack : Result := rsBlack; + scBlue : Result := rsBlue; + scBlueGray : Result := rsBlueGray; + scBrown : Result := rsBrown; + scCoral : Result := rsCoral; + scCyan : Result := rsCyan; + scDarkBlue : Result := rsDarkBlue; + scDarkGreen : Result := rsDarkGreen; + scDarkPurple : Result := rsDarkPurple; + scDarkRed : Result := rsDarkRed; + scDarkTeal : Result := rsDarkTeal; + scGold : Result := rsGold; + scGray : Result := rsGray; + scGray10pct : Result := rsGray10pct; + scGray20pct : Result := rsGray20pct; + scGray40pct : Result := rsGray40pct; + scGray80pct : Result := rsGray80pct; + scGreen : Result := rsGreen; + scIceBlue : Result := rsIceBlue; + scIndigo : Result := rsIndigo; + scIvory : Result := rsIvory; + scLavander : Result := rsLavander; + scLightBlue : Result := rsLightBlue; + scLightGreen : Result := rsLightGreen; + scLightOrange: Result := rsLightOrange; + scLightTurquoise: Result := rsLightTurquoise; + scLightYellow: Result := rsLightYellow; + scLime : Result := rsLime; + scMagenta : Result := rsMagenta; + scNavy : Result := rsNavy; + scOceanBlue : Result := rsOceanBlue; + scOlive : Result := rsOlive; + scOliveGreen : Result := rsOliveGreen; + scOrange : Result := rsOrange; + scPaleBlue : Result := rsPaleBlue; + scPeriwinkle : Result := rsPeriwinkle; + scPink : Result := rsPink; + scPlum : Result := rsPlum; + scPurple : Result := rsPurple; + scRed : Result := rsRed; + scRose : Result := rsRose; + scSeaGreen : Result := rsSeaGreen; + scSilver : Result := rsSilver; + scSkyBlue : Result := rsSkyBlue; + scTan : Result := rsTan; + scTeal : Result := rsTeal; + scVeryDarkGreen: Result := rsVeryDarkGreen; +// scViolet : Result := rsViolet; + scWheat : Result := rsWheat; + scWhite : Result := rsWhite; + scYellow : Result := rsYellow; + scTransparent: Result := rsTransparent; + scNotDefined : Result := rsNotDefined; + else + case rgba.a of + $00: + Result := Format('R%d G%d B%d', [rgba.r, rgba.g, rgba.b]); + scPaletteIndexMask shr 24: + Result := Format(rsPaletteIndex, [AColor and $00FFFFFF]); + else + Result := ''; + end; + end; +end; + +{@@ ---------------------------------------------------------------------------- + Returns a string describing the cell format with the specified index. +-------------------------------------------------------------------------------} +function GetCellFormatAsString(AWorkbook: TsWorkbook; AIndex: Integer): String; +var + fmt: PsCellFormat; + cb: TsCellBorder; + s: String; + numFmt: TsNumFormatParams; +begin + Result := ''; + fmt := GetPointerToCellFormat(AIndex); + if fmt = nil then + exit; + + if (uffFont in fmt^.UsedFormattingFields) then + Result := Format('%s; Font%d', [Result, fmt^.FontIndex]); + if (uffBackground in fmt^.UsedFormattingFields) then begin + Result := Format('%s; Bg %s', [Result, GetColorName(fmt^.Background.BgColor)]); + Result := Format('%s; Fg %s', [Result, GetColorName(fmt^.Background.FgColor)]); + Result := Format('%s; Pattern %s', [Result, GetEnumName(TypeInfo(TsFillStyle), ord(fmt^.Background.Style))]); + end; + if (uffHorAlign in fmt^.UsedFormattingfields) then + Result := Format('%s; %s', [Result, GetEnumName(TypeInfo(TsHorAlignment), ord(fmt^.HorAlignment))]); + if (uffVertAlign in fmt^.UsedFormattingFields) then + Result := Format('%s; %s', [Result, GetEnumName(TypeInfo(TsVertAlignment), ord(fmt^.VertAlignment))]); + if (uffWordwrap in fmt^.UsedFormattingFields) then + Result := Format('%s; Word-wrap', [Result]); + if (uffNumberFormat in fmt^.UsedFormattingFields) then + begin + numFmt := GetNumberFormat(fmt^.NumberFormatIndex); + if numFmt <> nil then + Result := Format('%s; %s (%s)', [Result, + GetEnumName(TypeInfo(TsNumberFormat), ord(numFmt.NumFormat)), + numFmt.NumFormatStr + ]) + else + Result := Format('%s; %s', [Result, 'nfGeneral']); + end else + Result := Format('%s; %s', [Result, 'nfGeneral']); + if (uffBorder in fmt^.UsedFormattingFields) then + begin + s := ''; + for cb in fmt^.Border do + if s = '' then s := GetEnumName(TypeInfo(TsCellBorder), ord(cb)) + else s := s + '+' + GetEnumName(TypeInfo(TsCellBorder), ord(cb)); + Result := Format('%s; %s', [Result, s]); + end; + if (uffBiDi in fmt^.UsedFormattingFields) then + Result := Format('%s; %s', [Result, GetEnumName(TypeInfo(TsBiDiMode), ord(fmt^.BiDiMode))]); + if Result <> '' then Delete(Result, 1, 2); +end; + +{@@ ---------------------------------------------------------------------------- + Returns a string which identifies the font. + + @param AIndex Index of the font + @return String with font name, font size etc. +-------------------------------------------------------------------------------} +function GetFontAsString(AFont: TsFont): String; +begin + if AFont <> nil then begin + Result := Format('%s; size %.1g; %s', [ + AFont.FontName, AFont.Size, GetColorName(AFont.Color)]); + if (fssBold in AFont.Style) then Result := Result + '; bold'; + if (fssItalic in AFont.Style) then Result := Result + '; italic'; + if (fssUnderline in AFont.Style) then Result := Result + '; underline'; + if (fssStrikeout in AFont.Style) then result := Result + '; strikeout'; + if AFont.Position = fpSubscript then Result := Result + '; subscript'; + if AFont.Position = fpSuperscript then Result := Result + '; superscript'; + end else + Result := ''; +end; + +end.