示例#1
0
        /// <summary>
        /// Check to see if the planetary hour (or lunar phase, if applicable) has changed.  If so, notify the user
        /// </summary>
        private void phTick(object sender, System.EventArgs e)
        {
            if (pHours.CurrentHour() == (PlanetaryHours.Planet)(-1))                            // Planetary day changed; recalculate hours
            {
                pHours = new PlanetaryHours(conf);
                // Just in case new hour is same as last recorded hour, but the computer had been suspended
                currentHour = (PlanetaryHours.Planet)(-2);                   // -2 because pHours.CurrentHour() could be -1 upon error.
            }

            if (currentHour != pHours.CurrentHour())
            {
                currentHour = pHours.CurrentHour();
                NotifyUser();
                updateTray();
                if (currentHour == (PlanetaryHours.Planet)(-1))
                {
                    ErrorMessage("An internal error has occured",
                                 new Exception("pHours.CurrentHour returns -1 twice - unable to calculate planetary hours"), conf);
                }
            }

            if (conf.Caption == Config.CaptionType.LunarPhase && currentPhase != localPhases.CurrentPhase(DateTime.UtcNow))
            {
                localPhases  = new LunarPhase(DateTime.UtcNow);
                currentPhase = localPhases.CurrentPhase(DateTime.UtcNow);
                updateTray();
            }
        }
示例#2
0
        /// <summary>
        /// This is called after the user clicks "Apply" or "OK" in the Properties form, in case the locality has changed.
        /// </summary>
        public void RefreshHours()
        {
            pHours = new PlanetaryHours(conf);
            if (pHours.CurrentHour() == (PlanetaryHours.Planet)(-1))
            {
                ErrorMessage("Unable to determine the current planetary hour.",
                             new Exception("pHours.GetHour returns null at UTC" + DateTime.UtcNow.ToString()), conf);
            }

            initContextMenu();
            if (conf.Caption == Config.CaptionType.LunarPhase)
            {
                localPhases  = new LunarPhase(DateTime.UtcNow);
                currentPhase = localPhases.CurrentPhase(DateTime.UtcNow);
            }
            updateTray();
            if (currentHour != pHours.CurrentHour())
            {
                currentHour = pHours.CurrentHour();
                NotifyUser();
            }
            phClock.Interval = conf.Interval();
        }
示例#3
0
        public ChronosXPCore(System.Windows.Application entry)
        {
            Entry = entry;

            Application.ApplicationExit += new System.EventHandler(appExit);
            Application.Idle            += new System.EventHandler(appIdle);

            conf = new Config(this);
            if (!conf.LoadOK)
            {
                Shutdown();
                return;
            }

            string[] args = Environment.GetCommandLineArgs();

            bool showproperties = false;

            // The command-line arguments should only be used for testing, or internally
            foreach (string arg in args)
            {
                switch (arg.ToLower())
                {
                case "/english":
                    conf.Language = Config.CultureEN;
                    break;

                case "/nederlands":
                case "/dutch":
                    conf.Language = Config.CultureNL;
                    break;

                case "/español":
                case "/espanol":
                case "/spanish":
                    conf.Language = Config.CultureES;
                    break;

                case "/italiano":
                case "/italian":
                    conf.Language = Config.CultureIT;
                    break;

                case "/français":
                case "/francais":
                case "/french":
                    conf.Language = Config.CultureFR;
                    break;

                case "/português":
                case "/portugues":
                case "/portuguese":
                    conf.Language = Config.CulturePT;
                    break;

                case "/hungarian":
                case "/magyar":
                    conf.Language = Config.CultureHU;
                    break;

                case "/greek":
                    conf.Language = Config.CultureGR;
                    break;

                case "/hebrew":
                    conf.Language = Config.CultureHE;
                    break;

                case "/standalone":
                    conf.RunFromTrayNow = false;
                    break;

                case "/tray":
                    conf.RunFromTrayNow = true;
                    break;

                case "/properties":
                    showproperties = true;
                    break;

                case "/nogradient":
                    conf.UseGradient = false;
                    break;

                case "/gradient":
                    conf.UseGradient = true;
                    break;

                case "/nocheckupdate":
                    checkUpdate = false;
                    break;

                case "/fastcheckupdate":
                    fastCheckUpdate = true;
                    break;

                                #if BETA
                case "/debugnotify":
                    debugnotify = true;
                    break;

                // This is to create screen-shots (for the web page) of a BETA, but make it look like a release.  Use with
                // /currentculture=(culture), to set Thread.CurrentCulture (which prints the VisualMonthCalendar in that language)
                // /photogenic implies /debugnotify
                case "/photogenic":
                    Photogenic  = true;
                    debugnotify = true;
                    break;
                                #endif
                default:
                    if (arg.ToLower().StartsWith("/zenith="))
                    {
                        string[] zz = arg.Split(new char[] { '=' }, 2);
                        try
                        {
                            conf.ZenithDistance = double.Parse(zz[1]);
                        }
                        catch
                        {
                            MessageBox.Show(conf.GetString("Core.InvalidArgument") + ": " + arg, "ChronosXP",
                                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                            Shutdown();
                            return;
                        }
                    }
                    else if (arg.ToLower().StartsWith("/iconset="))
                    {
                        string[] zz = arg.Split(new char[] { '=' }, 2);
                        if (zz[1].ToLower().Equals("silver") || zz[1].ToLower().Equals("black") || zz[1].ToLower().Equals("multi"))
                        {
                            conf.Fx.IconSet = zz[1];
                        }
                        else
                        {
                            MessageBox.Show(conf.GetString("Core.InvalidArgument") + ": " + arg, "ChronosXP",
                                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                            Shutdown();
                            return;
                        }
                    }
                    else if (arg.ToLower().StartsWith("/currentculture="))
                    {
                        string[] zz = arg.Split(new char[] { '=' }, 2);
                        try
                        {
                            conf.CurrentCulture                   = new CultureInfo(zz[1]);
                            Application.CurrentCulture            = conf.CurrentCulture;
                            Thread.CurrentThread.CurrentUICulture = conf.CurrentCulture;
                        }
                        catch
                        {
                            MessageBox.Show("Unsupported culture: " + zz[1], "ChronosXP",
                                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                            Shutdown();
                            return;
                        }
                    }
                    else
                    {
                        continue;
                        //MessageBox.Show (conf.GetString ("Core.InvalidArgument") + ": " + arg, "ChronosXP",
                        //    MessageBoxButtons.OK, MessageBoxIcon.Error);
                        //Application.Exit();
                        //return;
                    }
                    break;
                }
            }

            // tray mode?  initialize the NotifyIcon, ContextMenu and Timer, and calculate planetary hours.
            if (conf.RunFromTrayNow)
            {
                initTray();

                pHours      = new PlanetaryHours(conf);
                currentHour = pHours.CurrentHour();
                updateTray();

                if (conf.Caption == Config.CaptionType.LunarPhase)
                {
                    localPhases  = new LunarPhase(DateTime.UtcNow);
                    currentPhase = localPhases.CurrentPhase(DateTime.UtcNow);
                }

                // This timer checks to see if the planetary hour has changed; if so, notify the user (if applicable) and change the NotifyIcon
                // and it's ToolTip text.
                phClock          = new System.Windows.Forms.Timer();
                phClock.Interval = conf.Interval();
                phClock.Tick    += new System.EventHandler(phTick);
                phClock.Start();

                // This timer periodically updates the system tray icon;  this is to ensure that the ChronosXP is not hidden with the
                // inactive icons, and also because of a bug that makes the icon distorted after doing a <Windows key>+L
                trayClock          = new System.Windows.Forms.Timer();
                trayClock.Interval = 55555;
                trayClock.Tick    += new System.EventHandler(trayTick);
                trayClock.Start();

                // When in tray mode, bind Alt+F11 to open the Planetary Hours Calendar (see this.WndProc)
                PInvoke.RegisterHotKey(Handle, 101, PInvoke.MOD_ALT, PInvoke.VK_F11);
            }

                        #if WINDOWS
            if (conf.Run == 1)                     // First time ChronosXP is run?  Prompt user to configure locality
            {
                DialogResult res = MessageBox.Show(conf.GetString("Core.WelcomeText"), conf.GetString("Core.WelcomeTitle"),
                                                   MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (res == DialogResult.Yes)
                {
                    ShowProperties();
                }
                else
                {
                    MessageBox.Show(conf.GetString("Core.NoConfigText"), conf.GetString("Core.NoConfigTitle"),
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
                        #endif

                        #if BETA
            if (conf.BetaExpiry.CompareTo(DateTime.Now) <= 0)              // Beta expired?  Prompt user to upgrade
            {
                auxThread = new Thread(new ThreadStart(threadBetaExpired));
                auxThread.Start();

                if (conf.RunFromTrayNow)
                {
                    betaClock          = new System.Windows.Forms.Timer();
                    betaClock.Interval = 2255555;
                    betaClock.Tick    += new System.EventHandler(betaWarnTick);
                    betaClock.Start();
                }
            }
            else
                        #endif // BETA

                        #if WINDOWS
            // First, second or third time ChronosXP is run?  Notify user that its running in the background with a balloon window
            if (conf.Run < 3 && conf.RunFromTrayNow)
            {
                auxThread = new Thread(new ThreadStart(threadBgRunning));
                auxThread.Start();
            }
                        #endif // WINDOWS

            //if !DEBUG
            CheckUpdates();
            //endif / DEBUG

            // standalone mode?  display the Planetary Hours Calendar
            if (!conf.RunFromTrayNow)
            {
                ShowCalendar();
            }

            // run with /properties argument?  Show the Properties form.
            if (showproperties)
            {
                ShowProperties();
            }
        }
示例#4
0
        /// <summary>
        /// Update the tray icon
        /// </summary>
        private void updateTray()
        {
            if (conf.Caption == Config.CaptionType.LunarPhase && localPhases == null)
            {
                localPhases  = new LunarPhase(DateTime.UtcNow);
                currentPhase = localPhases.CurrentPhase(DateTime.UtcNow);
            }

            if (currentHour == (PlanetaryHours.Planet)(-1))
            {
                pHours      = new PlanetaryHours(conf);
                currentHour = pHours.CurrentHour();
            }

            if (currentHour == (PlanetaryHours.Planet)(-1))
            {
                trayIcon.Icon = new Icon(conf.Fx.ResourceStream("Exclamation.ico"));
                ErrorMessage("A serious internal error has occured; please report this error to the author of ChronosXP at " + Config.Email,
                             new Exception("ChronosXP.PlanetaryHours failed twice at " + DateTime.Now.ToString() + "; unable to determine planetary hour."),
                             conf);
            }
            else
            {
                try
                {
                    if (conf.Fx.IconSet.Equals("Silver") && pHours.CurrentHour() == PlanetaryHours.Planet.Saturn)
                    {
                        trayIcon.Icon = conf.Fx.GlyphIconSmall("Tray.Saturn");
                    }
                    else
                    {
                        trayIcon.Icon = conf.Fx.GlyphIconSmall(pHours.CurrentEnglishHour());
                    }
                    string stat;
                    switch (conf.Caption)
                    {
                    default:
                    case Config.CaptionType.HourNumber:
                        stat = pHours.HourOfDay(DateTime.Now);
                        break;

                    case Config.CaptionType.HouseOfMoment:
                        stat = pHours.HouseOfMoment(DateTime.Now);
                        break;

                    case Config.CaptionType.LunarPhase:
                        int i = localPhases.PhaseNum(DateTime.UtcNow);
                        if (i == -1)
                        {
                            i = 7;
                        }
                        stat = conf.GetString(LunarPhase.PhaseName[i]);
                        break;
                    }
                    string s = pHours.DayString() + "\r\n" + pHours.CurrentHourString() + "\r\n" + stat;
                    // Too bad we're limited to 64 chars, because this would be nice...
                    //string s = pHours.DayString() +  ", " + pHours.CurrentHourString() + "\r\n" +
                    //	pHours.HourOfDay(DateTime.Now) + ", " + pHours.HouseOfMoment(DateTime.Now) + "\r\n" +
                    //	localPhases.PhaseNum(DateTime.UtcNow);
                    if (s.Length >= 64)
                    {
                        s = s.Remove(60, s.Length - 60) + "...";
                    }
                    trayIcon.Text = s;
                }
                catch (Exception ex)
                {
                    trayIcon.Icon = new Icon(conf.Fx.ResourceStream("Exclamation.ico"));
                    ErrorMessage("Unable to set glyph icon.  [CurrentEnglishHour=" + pHours.CurrentEnglishHour() + "]", ex);
                }
            }
        }
示例#5
0
        private int printDiary(DateTime when, System.Drawing.Printing.PrintPageEventArgs e, int curpg, int pgtotal)
        {
            PlanetaryHours pHours   = new PlanetaryHours(when, where, conf);
            Font           hdfont   = new Font(Font.Name, 15.0F, FontStyle.Bold);
            Font           sfont    = new Font(Font.Name, 11.0F);
            Font           hrfont   = new Font(Font.Name, 10.0F);
            Font           hrhdfont = new Font(Font.Name, 11.0F, FontStyle.Bold);

            float x, y;  bool hdrPrinted = false;

            if (printHr == 0)
            {
                displayHr  = 0;
                hdrPrinted = true;
                float picx = e.MarginBounds.Left;
                Image im   = Image.FromStream(conf.Fx.GlyphGif(pHours.EnglishDay()));
                x = picx + im.Width + 11;
                y = e.MarginBounds.Top;

                e.Graphics.DrawString(pHours.DayString(), hdfont, Brushes.Black, x, y, StringFormat.GenericDefault);
                y += e.Graphics.MeasureString(pHours.DayString(), hdfont, new PointF(x, y), StringFormat.GenericDefault).Height;

                string whenwhere = when.ToLongDateString() + " - " + where.Name;
                e.Graphics.DrawString(whenwhere, sfont, Brushes.Black, x + 1, y, StringFormat.GenericDefault);
                y += e.Graphics.MeasureString(whenwhere, sfont, new PointF(x, y), StringFormat.GenericDefault).Height + 2;

                string risetext, settext;
                if (!pHours.RS.SunRises)
                {
                    risetext = String.Format(conf.Res.GetString("Calendar.NoSunRiseSet"),
                                             conf.Res.GetString("Rise"), when.ToShortDateString(), where.Name);
                }
                else
                {
                    risetext = String.Format(conf.Res.GetString("Calendar.labelSunrise"),
                                             conf.FormatTime(pHours.Hours[0].StartTime),
                                             where.UseSystemTime ? "" : (" " + where.ZoneAbbreviation));
                }
                if (!pHours.RS.SunSets)
                {
                    settext = String.Format(conf.Res.GetString("Calendar.NoSunRiseSet"),
                                            conf.Res.GetString("Set"), when.ToShortDateString(), where.Name);
                }
                else
                {
                    settext = String.Format(conf.Res.GetString("Calendar.labelSunset"),
                                            conf.FormatTime(pHours.Hours[12].StartTime),
                                            where.UseSystemTime ? "": (" " + where.ZoneAbbreviation));
                }

                string riseset = risetext + " - " + settext;
                e.Graphics.DrawString(riseset, sfont, Brushes.Black, x + 1, y, StringFormat.GenericDefault);
                y += e.Graphics.MeasureString(riseset, sfont, new PointF(x, y), StringFormat.GenericDefault).Height + 2;

                float picy = e.MarginBounds.Top + (((y - e.MarginBounds.Top) - im.Height) / 2);
                if (y < (e.MarginBounds.Top + im.Height))
                {
                    y = picy + im.Height + 5;
                }

                e.Graphics.DrawImage(im, picx, picy);

                x = e.MarginBounds.Left;  y += 11;
                e.Graphics.DrawLine(Pens.Gray, x, y, x + e.MarginBounds.Width, y);
                y += 33;
            }
            else
            {
                x = e.MarginBounds.Left;
                y = e.MarginBounds.Top;
                string str = String.Format("{0} - {1} - {2}", pHours.DayString(), when.ToLongDateString(), where.Name);
                e.Graphics.DrawString(str, hrhdfont, Brushes.Black, x, y, StringFormat.GenericDefault);
                y += e.Graphics.MeasureString(str, hrhdfont, new PointF(x, y), StringFormat.GenericDefault).Height + 22;
            }

            float ght = hrfont.Height * 4;

            if (!hdrPrinted)
            {
                ght += hrfont.Height / 2;
            }
            TimeSpan os = new TimeSpan(0, 0, 1);

            while ((y + ght) <= e.MarginBounds.Bottom && printHr != 24)
            {
                if (inBounds(pHours.Hours[printHr].StartTime))
                {
                    displayHr++;
                    PlanetaryHours.Planet pl = pHours.Hours[printHr].Hour;
                    string displaystr        = pHours.HourString(pl) + " (";
                    if (printHr == 0)
                    {
                        displaystr += conf.GetString("Sunrise") + ", ";
                    }
                    else if (printHr == 12)
                    {
                        displaystr += conf.GetString("Sunset") + ", ";
                    }
                    displaystr += conf.FormatTime(pHours.Hours[printHr].StartTime) + " - " +
                                  conf.FormatTime(pHours.Hours[printHr + 1].StartTime.Subtract(os)) + ")";
                    e.Graphics.DrawString(displaystr, hrfont, Brushes.Black, x, y, StringFormat.GenericDefault);
                    float incr = e.Graphics.MeasureString(pHours.PlanetName(pl), hrfont, new PointF(x, y), StringFormat.GenericDefault).Height;
                    y += (incr * 2);
                    if (conf.PrintGlyphs)
                    {
                        RectangleF rf = new RectangleF(x, y + 1, 16, 16);
                        Image      im = Image.FromStream(conf.Fx.GlyphIconAsStream(Color.Black, pHours.EnglishName(pl)));
                        e.Graphics.DrawImage(im, rf);
                        e.Graphics.DrawLine(Pens.Gray, x + im.Width + 7, y, x + e.MarginBounds.Width, y);
                        y += incr;
                        e.Graphics.DrawLine(Pens.Gray, x + im.Width + 7, y, x + e.MarginBounds.Width, y);
                        y += incr;
                    }
                    else
                    {
                        e.Graphics.DrawLine(Pens.Gray, x, y, x + e.MarginBounds.Width, y);
                        y += incr;
                        e.Graphics.DrawLine(Pens.Gray, x, y, x + e.MarginBounds.Width, y);
                        y += incr;
                    }
                    // The first page has a long header; if not printing the first page, compensate for the absense of this header
                    if (hdrPrinted)
                    {
                        y += incr / 2;
                    }
                }
                printHr++;
            }

            string ver = Config.FormatVersion();
            SizeF  vsz = e.Graphics.MeasureString(ver, hrfont, e.MarginBounds.Width, StringFormat.GenericDefault);

            e.Graphics.DrawString(ver, hrfont, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Bottom - vsz.Height,
                                  StringFormat.GenericDefault);

            // Try to calculate the number of pages.  A better way to do this would instead be, before printing, creating an array of Graphics surfaces
            // with each page.  When the page number is known, go back and write the "Page __ of __" to each surface.  Then, BitBlt() the appropriate
            // Graphics surface to e.Graphics.  I don't envision this algorithm will be innaccurate, but I think it might be possible, especially with the "wrong"
            // size paper.
            int pgs, hrs = 0;

            foreach (PlanetaryHours.PlanetaryHour ph in pHours.Hours)
            {
                if (inBounds(ph.StartTime))
                {
                    hrs++;
                }
            }
            if (pgtotal == 0)
            {
                if (printHr == 24)
                {
                    pgs = pageNo;
                }
                else if (radioButtonPrintAll.Checked)
                {
                    pgs = 24 / (printHr / pageNo);
                    if ((printHr * pgs) < 24)
                    {
                        pgs++;
                    }
                }
                else
                {
                    if (hrs > 9)
                    {
                        pgs = (hrs - 9) / 11;
                        if ((displayHr * pgs) + 9 < hrs)
                        {
                            pgs++;
                        }
                        pgs++;
                    }
                    else
                    {
                        pgs = 1;
                    }
                }
            }
            else
            {
                pgs = pgtotal;
            }
            string pg   = String.Format(conf.GetString("Print.PageOf"), pageNo, pgs);
            SizeF  tdsz = e.Graphics.MeasureString(pg, hrfont, e.MarginBounds.Width, StringFormat.GenericDefault);

            e.Graphics.DrawString(pg, hrfont, Brushes.Black, e.MarginBounds.Right - tdsz.Width, e.MarginBounds.Bottom - tdsz.Height, StringFormat.GenericDefault);

            if (pageNo != pageTotal)
            {
                e.HasMorePages = true;
            }

            if (printHr == 24 || hrs == displayHr)
            {
                printHr = 0;
                dayNo++;
            }

            return(pgs);
        }
示例#6
0
        private void printNormal(DateTime when, System.Drawing.Printing.PrintPageEventArgs e, int curpg, int pgtotal)
        {
            PlanetaryHours pHours   = new PlanetaryHours(when, where, conf);
            Font           hdfont   = new Font(Font.Name, 15.0F, FontStyle.Bold);
            Font           sfont    = new Font(Font.Name, 11.0F);
            Font           hrfont   = new Font(Font.Name, 10.0F);
            Font           hrhdfont = new Font(Font.Name, 11.0F, FontStyle.Bold);

            float picx = e.MarginBounds.Left;
            Image dyim = Image.FromStream(conf.Fx.GlyphGif(pHours.EnglishDay()));
            float x    = picx + dyim.Width + 11;
            float y    = e.MarginBounds.Top;

            // Previously we used no StringFormat in DrawString and MeasureString, which made text (mainly at the lower-left margin) not formatted correctly.
            // Thanks to a microsoft.public.dotnet.languages.csharp posting by Ron Allen, we now use StringFormat.GenericDefault
            e.Graphics.DrawString(pHours.DayString(), hdfont, Brushes.Black, x, y, StringFormat.GenericDefault);
            y += e.Graphics.MeasureString(pHours.DayString(), hdfont, new PointF(x, y), StringFormat.GenericDefault).Height;

            string whenwhere = when.ToLongDateString() + " - " + where.Name;

            e.Graphics.DrawString(whenwhere, sfont, Brushes.Black, x + 1, y, StringFormat.GenericDefault);
            y += e.Graphics.MeasureString(whenwhere, sfont, new PointF(x, y), StringFormat.GenericDefault).Height + 2;

            string risetext, settext;

            if (!pHours.RS.SunRises)            //(!pHours.RiseSet.SunRises)
            {
                risetext = String.Format(conf.Res.GetString("Calendar.NoSunRiseSet"),
                                         conf.Res.GetString("Rise"), when.ToShortDateString(), where.Name);
            }
            else
            {
                risetext = String.Format(conf.Res.GetString("Calendar.labelSunrise"),
                                         conf.FormatTime(pHours.Hours[0].StartTime),
                                         where.UseSystemTime ? "" : (" " + where.ZoneAbbreviation));
            }
            if (!pHours.RS.SunSets)
            {
                settext = String.Format(conf.Res.GetString("Calendar.NoSunRiseSet"),
                                        conf.Res.GetString("Set"), when.ToShortDateString(), where.Name);
            }
            else
            {
                settext = String.Format(conf.Res.GetString("Calendar.labelSunset"),
                                        conf.FormatTime(pHours.Hours[12].StartTime),
                                        where.UseSystemTime ? "": (" " + where.ZoneAbbreviation));
            }

            string riseset = risetext + " - " + settext;

            e.Graphics.DrawString(riseset, sfont, Brushes.Black, x + 1, y, StringFormat.GenericDefault);
            y += e.Graphics.MeasureString(riseset, sfont, new PointF(x, y), StringFormat.GenericDefault).Height + 2;

            float picy = e.MarginBounds.Top + (((y - e.MarginBounds.Top) - dyim.Height) / 2);

            if (y < (e.MarginBounds.Top + dyim.Height))
            {
                y = picy + dyim.Height + 5;
            }

            e.Graphics.DrawImage(dyim, picx, picy);

            x = e.MarginBounds.Left;  y += 11;
            e.Graphics.DrawLine(Pens.Gray, x, y, x + e.MarginBounds.Width, y);
            y += 22;

            e.Graphics.DrawString(conf.Res.GetString("Calendar.DayHours"), hrhdfont, Brushes.Black, x, y, StringFormat.GenericDefault);
            e.Graphics.DrawString(conf.Res.GetString("Calendar.NightHours"), hrhdfont, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width / 2), y, StringFormat.GenericDefault);
            y += e.Graphics.MeasureString(conf.Res.GetString("Calendar.DayHours"), hrhdfont, new PointF(x, y), StringFormat.GenericDefault).Height + 9;
            float savey = y;

            for (int hr = 0; hr < 24; hr++)
            {
                if (hr == 12)
                {
                    y = savey;
                    x = e.MarginBounds.Left + (e.MarginBounds.Width / 2);
                }
                PlanetaryHours.Planet pl = pHours.Hours[hr].Hour;
                RectangleF            rf = new RectangleF(x, y, 16, 16);
                Image im;
                if (conf.PrintGlyphs)
                {
                    im = Image.FromStream(conf.Fx.GlyphIconAsStream(Color.Black, pHours.EnglishName(pl)));
                    e.Graphics.DrawImage(im, rf);
                }
                else
                {
                    im = new Bitmap(1, 1);
                }
                e.Graphics.DrawString(pHours.PlanetName(pl), hrfont, Brushes.Black, x + (conf.PrintGlyphs ? im.Width + 5 : 0), y, StringFormat.GenericDefault);
                e.Graphics.DrawString(conf.FormatTime(pHours.Hours[hr].StartTime), hrfont, Brushes.Black, x + 112, y, StringFormat.GenericDefault);
                if (conf.PrintGlyphs)
                {
                    y += im.Height + 5;
                }
                else
                {
                    y += e.Graphics.MeasureString(pHours.PlanetName(pl), hrfont, new PointF(x, y), StringFormat.GenericDefault).Height;
                }
            }

            string ver = Config.FormatVersion();
            SizeF  vsz = e.Graphics.MeasureString(ver, hrfont, e.MarginBounds.Width, StringFormat.GenericDefault);

            e.Graphics.DrawString(ver, hrfont, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Bottom - vsz.Height,
                                  StringFormat.GenericDefault);
            string pg   = String.Format(conf.GetString("Print.PageOf"), curpg, pgtotal);
            SizeF  tdsz = e.Graphics.MeasureString(pg, hrfont, e.MarginBounds.Width, StringFormat.GenericDefault);

            e.Graphics.DrawString(pg, hrfont, Brushes.Black, e.MarginBounds.Right - tdsz.Width, e.MarginBounds.Bottom - tdsz.Height, StringFormat.GenericDefault);

            if (curpg != pgtotal)
            {
                e.HasMorePages = true;
            }
            dayNo++;
        }