private void ExposeCatalog(Document document, SimpleColumnText columnText, CatalogProps catProps)
        {
            StringList index = catProps.Index;

            if (index == null)
            {
                return;
            }

            Chunk chunk = new Chunk(catProps.Title, fSubchapFont);

            chunk.SetLocalDestination(catProps.Sign);

            if (CatalogNewPages)
            {
                document.Add(new Paragraph(chunk));
                document.Add(new Paragraph(Chunk.NEWLINE));
            }
            else
            {
                columnText.AddElement(new Paragraph(chunk)
                {
                    Alignment = 1
                });
                columnText.AddElement(new Paragraph(Chunk.NEWLINE));
            }

            index.Sort();
            int num = index.Count;

            for (int i = 0; i < num; i++)
            {
                Paragraph ps = new Paragraph(new Chunk(index[i], fSymFont));
                ps.SpacingBefore = 0f;
                ps.SpacingAfter  = 20f;
                //ps.Alignment = 1;
                ps.Add(Chunk.NEWLINE);
                columnText.AddElement(ps);

                StringList persons = (StringList)index.GetObject(i);

                persons.Sort();
                int num2 = persons.Count;
                for (int k = 0; k < num2; k++)
                {
                    GEDCOMIndividualRecord iRec = (GEDCOMIndividualRecord)persons.GetObject(k);

                    chunk = new Chunk(persons[k], fTextFont);
                    chunk.SetLocalGoto(iRec.XRef);
                    Paragraph p = new Paragraph(chunk);
                    columnText.AddElement(p);
                }

                columnText.AddElement(new Paragraph(Chunk.NEWLINE)
                {
                    SpacingAfter = 10f
                });
            }
        }
        private void ExposeCatalog(CatalogProps catProps)
        {
            StringList index = catProps.Index;

            if (index == null)
            {
                return;
            }

            fWriter.BeginParagraph(TextAlignment.taCenter, 0, 0, 0);
            fWriter.AddParagraphAnchor(catProps.Title, fSubchapFont, catProps.Sign);
            fWriter.EndParagraph();
            fWriter.NewLine();

            index.Sort();
            int num = index.Count;

            for (int i = 0; i < num; i++)
            {
                fWriter.BeginParagraph(TextAlignment.taLeft, 0, 20, 0);
                fWriter.AddParagraphChunk(index[i], fSymFont);
                fWriter.EndParagraph();
                fWriter.NewLine();

                StringList persons = (StringList)index.GetObject(i);

                persons.Sort();
                int num2 = persons.Count;
                for (int k = 0; k < num2; k++)
                {
                    GDMIndividualRecord iRec = (GDMIndividualRecord)persons.GetObject(k);

                    fWriter.BeginParagraph(TextAlignment.taLeft, 0, 0, 0);
                    fWriter.AddParagraphChunkLink(persons[k], fTextFont, iRec.XRef);
                    fWriter.EndParagraph();
                }

                fWriter.NewLine(0, 10f);
            }
        }
        protected override void InternalGenerate()
        {
            try {
                PrepareData();

                IColor clrBlack = AppHost.GfxProvider.CreateColor(0x000000);
                IColor clrBlue  = AppHost.GfxProvider.CreateColor(0x0000FF);

                fTitleFont   = fWriter.CreateFont("", 30f, true, false, clrBlack);
                fChapFont    = fWriter.CreateFont("", 16f, true, false, clrBlack);
                fSubchapFont = fWriter.CreateFont("", 14f, true, false, clrBlack);
                fLinkFont    = fWriter.CreateFont("", 8f, false, true, clrBlue);
                fTextFont    = fWriter.CreateFont("", 8f, false, false, clrBlack);
                fBoldFont    = fWriter.CreateFont("", 8f, true, false, clrBlack);
                fSymFont     = fWriter.CreateFont("", 12f, true, false, clrBlack);

                fWriter.EnablePageNumbers();

                var   pageSize = fWriter.GetPageSize();
                float halfpage = (pageSize.GetHeight() - (fTitleFont.Size * 4)) / 2f;
                fWriter.NewLine(0.0f, halfpage);
                fWriter.AddParagraph(fTitle, fTitleFont, TextAlignment.taCenter);
                fWriter.NewPage();

                fWriter.AddParagraph(LangMan.LS(LSID.LSID_TableOfContents), fChapFont);
                fWriter.NewLine();
                fWriter.AddParagraphLink("1. " + LangMan.LS(LSID.LSID_PersonalRecords), fLinkFont, "IndividualRecords");
                fWriter.AddParagraphLink("2. " + LangMan.LS(LSID.LSID_Indexes), fLinkFont, "Catalogs");

                int catNum = 0;
                for (BookCatalog cat = BookCatalog.Catalog_First; cat <= BookCatalog.Catalog_Last; cat++)
                {
                    CatalogProps catProps = BookCatalogs[(int)cat];

                    if (!SkipEmptyCatalogs || catProps.Index.Count > 0)
                    {
                        catNum++;
                        string title = "2." + catNum.ToString() + ". " + catProps.Title;

                        fWriter.BeginParagraph(TextAlignment.taLeft, 0.0f, 0.0f, 1f);
                        fWriter.AddParagraphChunkLink(title, fLinkFont, catProps.Sign);
                        fWriter.EndParagraph();
                    }
                }

                fWriter.NewPage();

                fWriter.BeginParagraph(TextAlignment.taCenter, 0, 20f);
                fWriter.AddParagraphChunkAnchor(LangMan.LS(LSID.LSID_PersonalRecords), fChapFont, "IndividualRecords");
                fWriter.EndParagraph();
                fWriter.NewLine();

                fWriter.BeginMulticolumns(3, 10f);
                char sym = '!';
                int  num = mainIndex.Count;
                for (int i = 0; i < num; i++)
                {
                    string text = mainIndex[i];
                    GDMIndividualRecord iRec = mainIndex.GetObject(i) as GDMIndividualRecord;

                    char isym = (string.IsNullOrEmpty(text)) ? '?' : text[0];
                    if ((isym >= 'A' && isym <= 'Z') || (isym >= 'А' && isym <= 'Я'))
                    {
                        if (sym != isym)
                        {
                            fWriter.AddParagraph("" + isym, fSymFont, TextAlignment.taCenter);
                            fWriter.NewLine();
                            sym = isym;
                        }
                    }

                    ExposePerson(iRec, text);

                    fWriter.NewLine();
                }
                fWriter.EndMulticolumns();

                fWriter.NewPage();

                fWriter.BeginParagraph(TextAlignment.taCenter, 0, 20f);
                fWriter.AddParagraphChunkAnchor(LangMan.LS(LSID.LSID_Indexes), fChapFont, "Catalogs");
                fWriter.EndParagraph();
                fWriter.NewLine();

                fWriter.BeginMulticolumns(3, 10f);
                for (BookCatalog cat = BookCatalog.Catalog_First; cat <= BookCatalog.Catalog_Last; cat++)
                {
                    CatalogProps catProps = BookCatalogs[(int)cat];

                    if (!SkipEmptyCatalogs || catProps.Index.Count > 0)
                    {
                        if (CatalogNewPages)
                        {
                            fWriter.NewPage();
                            fWriter.BeginMulticolumns(3, 10f);
                        }

                        ExposeCatalog(catProps);
                    }
                }

                fWriter.EndMulticolumns();
            } catch (Exception ex) {
                Logger.WriteError("FamilyBookExporter.InternalGenerate()", ex);
                throw;
            }
        }
        /*private void AddParagraph(Chunk chunk, int alignment = Element.ALIGN_LEFT)
         * {
         *  fDocument.Add(new Paragraph(chunk) { Alignment = alignment });
         * }*/

        protected override void InternalGenerate()
        {
            try
            {
                PrepareData();

                fDocument.AddTitle("FamilyBook");
                fDocument.AddSubject("FamilyBook");
                fDocument.AddAuthor("");
                fDocument.AddCreator(GKData.APP_TITLE);
                fDocument.Open();

                BaseFont baseFont = BaseFont.CreateFont(Environment.ExpandEnvironmentVariables(@"%systemroot%\fonts\Times.ttf"), "CP1251", BaseFont.EMBEDDED);
                fTitleFont   = new itFont(baseFont, 30f, Font.BOLD);
                fChapFont    = new itFont(baseFont, 16f, Font.BOLD, BaseColor.BLACK);
                fSubchapFont = new itFont(baseFont, 14f, Font.BOLD, BaseColor.BLACK);
                fLinkFont    = new itFont(baseFont, 8f, Font.UNDERLINE, BaseColor.BLUE);
                fTextFont    = new itFont(baseFont, 8f, Font.NORMAL, BaseColor.BLACK);
                fBoldFont    = new itFont(baseFont, 8f, Font.BOLD, BaseColor.BLACK);
                fSymFont     = new itFont(baseFont, 12f, Font.BOLD, BaseColor.BLACK);

                baseFont = BaseFont.CreateFont(Environment.ExpandEnvironmentVariables(@"%systemroot%\fonts\Calibri.ttf"), "CP1251", BaseFont.EMBEDDED);
                //Font page_font = new Font(base_font, 9f, Font.NORMAL);

                fPdfWriter.PageEvent = new PDFWriterEvents(baseFont, LangMan.LS(LSID.LSID_Page) + ": ");

                float halfpage = (fDocument.Top - fDocument.Bottom - (fTitleFont.Size) * 4) / 2f;
                fDocument.Add(new Paragraph(Chunk.NEWLINE)
                {
                    SpacingAfter = halfpage
                });
                fDocument.Add(new Paragraph(LangMan.LS(LSID.LSID_FamilyBook), fTitleFont)
                {
                    Alignment = Element.ALIGN_CENTER
                });
                fDocument.NewPage();

                Chunk chapChunk = new Chunk(LangMan.LS(LSID.LSID_TableOfContents), fChapFont);
                fDocument.Add(new Paragraph(chapChunk));
                fDocument.Add(new Paragraph(Chunk.NEWLINE));

                chapChunk = new Chunk("1. " + LangMan.LS(LSID.LSID_PersonalRecords), fLinkFont);
                chapChunk.SetLocalGoto("IndividualRecords");
                fDocument.Add(new Paragraph(chapChunk));

                chapChunk = new Chunk("2. " + LangMan.LS(LSID.LSID_Indexes), fLinkFont);
                chapChunk.SetLocalGoto("Catalogs");
                fDocument.Add(new Paragraph(chapChunk));

                // debug

                /*Rectangle pgSize = fDocument.PageSize;
                 *              fDocument.Add(new Paragraph(Chunk.NEWLINE));
                 *              chap_chunk = new Chunk(pgSize.Height.ToString() + " / " + pgSize.Width.ToString(), fChapFont);
                 *              fDocument.Add(new Paragraph(chap_chunk) { Alignment = 1 });*/

                int catNum = 0;
                for (BookCatalog cat = BookCatalog.Catalog_First; cat <= BookCatalog.Catalog_Last; cat++)
                {
                    CatalogProps catProps = BookCatalogs[(int)cat];

                    if (!SkipEmptyCatalogs || catProps.Index.Count > 0)
                    {
                        catNum++;
                        string title = "2." + catNum.ToString() + ". " + catProps.Title;

                        chapChunk = new Chunk(title, fLinkFont);
                        chapChunk.SetLocalGoto(catProps.Sign);
                        fDocument.Add(new Paragraph(chapChunk)
                        {
                            IndentationLeft = 1f
                        });
                    }
                }

                fDocument.NewPage();

                chapChunk = new Chunk(LangMan.LS(LSID.LSID_PersonalRecords), fChapFont);
                chapChunk.SetLocalDestination("IndividualRecords");
                fDocument.Add(new Paragraph(chapChunk)
                {
                    Alignment = 1, SpacingAfter = 20f
                });
                fDocument.Add(new Paragraph(Chunk.NEWLINE));

                SimpleColumnText columnText = new SimpleColumnText(fDocument, fPdfWriter.DirectContent, 3, 10f);
                float            pageWidth  = fDocument.PageSize.Width - fDocument.LeftMargin - fDocument.RightMargin;
                float            colWidth   = (pageWidth - (10f * 2)) / 3;

                char sym = '!';
                int  num = mainIndex.Count;
                for (int i = 0; i < num; i++)
                {
                    string text = mainIndex[i];
                    GEDCOMIndividualRecord iRec = mainIndex.GetObject(i) as GEDCOMIndividualRecord;

                    char isym = text[0];
                    if ((isym >= 'A' && isym <= 'Z') || (isym >= 'А' && isym <= 'Я'))
                    {
                        if (sym != isym)
                        {
                            Paragraph ps = new Paragraph(new Chunk(isym, fSymFont));
                            ps.Alignment = 1;
                            columnText.AddElement(ps);
                            columnText.AddElement(new Paragraph(Chunk.NEWLINE));
                            sym = isym;
                        }
                    }

                    ExposePerson(columnText, iRec, text, colWidth);

                    columnText.AddElement(new Paragraph(Chunk.NEWLINE));
                }

                fDocument.NewPage();

                chapChunk = new Chunk(LangMan.LS(LSID.LSID_Indexes), fChapFont);
                chapChunk.SetLocalDestination("Catalogs");
                fDocument.Add(new Paragraph(chapChunk)
                {
                    Alignment = 1
                });
                fDocument.Add(new Paragraph(Chunk.NEWLINE));

                //SimpleColumnText columnText;
                if (!CatalogNewPages)
                {
                    columnText = new SimpleColumnText(fDocument, fPdfWriter.DirectContent, 3, 10f);
                }

                for (BookCatalog cat = BookCatalog.Catalog_First; cat <= BookCatalog.Catalog_Last; cat++)
                {
                    CatalogProps catProps = BookCatalogs[(int)cat];

                    if (!SkipEmptyCatalogs || catProps.Index.Count > 0)
                    {
                        if (CatalogNewPages)
                        {
                            fDocument.NewPage();
                            columnText = new SimpleColumnText(fDocument, fPdfWriter.DirectContent, 3, 10f);
                        }

                        ExposeCatalog(fDocument, columnText, catProps);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogWrite("FamilyBookExporter.InternalGenerate(): " + ex.Message);
                throw;
            }
        }