From 743660448317ac0a0e806f27945fe75e358e2b3d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 27 Oct 2018 12:14:02 -0700 Subject: GLK: Added time and date glk functions --- engines/gargoyle/glk.cpp | 59 ++++++++++++++-------- engines/gargoyle/glk.h | 20 ++++---- engines/gargoyle/glk_types.h | 23 --------- engines/gargoyle/module.mk | 1 + engines/gargoyle/streams.cpp | 5 ++ engines/gargoyle/streams.h | 9 ++++ engines/gargoyle/time.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++ engines/gargoyle/time.h | 93 ++++++++++++++++++++++++++++++++++ 8 files changed, 272 insertions(+), 56 deletions(-) create mode 100644 engines/gargoyle/time.cpp create mode 100644 engines/gargoyle/time.h (limited to 'engines') diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp index c38548246b..f1b24cb25b 100644 --- a/engines/gargoyle/glk.cpp +++ b/engines/gargoyle/glk.cpp @@ -857,11 +857,12 @@ void Glk::glk_schannel_set_volume_ext(schanid_t chan, glui32 vol, } void Glk::glk_set_hyperlink(glui32 linkval) { - // TODO + _streams->getCurrent()->setHyperlink(linkval); } void Glk::glk_set_hyperlink_stream(strid_t str, glui32 linkval) { - // TODO + if (str) + str->setHyperlink(linkval); } void Glk::glk_request_hyperlink_event(winid_t win) { @@ -873,50 +874,64 @@ void Glk::glk_request_hyperlink_event(winid_t win) { } void Glk::glk_cancel_hyperlink_event(winid_t win) { - // TODO + if (win) { + win->cancelHyperlinkEvent(); + } else { + warning("cancel_hyperlink_event: invalid ref"); + } } void Glk::glk_current_time(glktimeval_t *time) { - // TODO + TimeAndDate td; + *time = td; } glsi32 Glk::glk_current_simple_time(glui32 factor) { - // TODO - return 0; + assert(factor); + TimeAndDate td; + + return td / factor; } -void Glk::glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date) { - // TODO +void Glk::glk_time_to_date_utc(const glktimeval_t *time, glkdate_t *date) { + // TODO: timezones aren't currently supported + *date = TimeAndDate(*time); } -void Glk::glk_time_to_date_local(glktimeval_t *time, glkdate_t *date) { - // TODO +void Glk::glk_time_to_date_local(const glktimeval_t *time, glkdate_t *date) { + *date = TimeAndDate(*time); } void Glk::glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date) { - // TODO + TimeSeconds secs = (int64)time * factor; + *date = TimeAndDate(secs); } void Glk::glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date) { - // TODO + TimeSeconds secs = (int64)time * factor; + *date = TimeAndDate(secs); } -void Glk::glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time) { - // TODO +void Glk::glk_date_to_time_utc(const glkdate_t *date, glktimeval_t *time) { + // TODO: timezones aren't currently supported + *time = TimeAndDate(*date); } -void Glk::glk_date_to_time_local(glkdate_t *date, glktimeval_t *time) { - // TODO +void Glk::glk_date_to_time_local(const glkdate_t *date, glktimeval_t *time) { + *time = TimeAndDate(*date); } -glsi32 Glk::glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor) { - // TODO - return 0; +glsi32 Glk::glk_date_to_simple_time_utc(const glkdate_t *date, glui32 factor) { + // TODO: timezones aren't currently supported + assert(factor); + TimeSeconds ts = TimeAndDate(*date); + return ts / factor; } -glsi32 Glk::glk_date_to_simple_time_local(glkdate_t *date, glui32 factor) { - // TODO - return 0; +glsi32 Glk::glk_date_to_simple_time_local(const glkdate_t *date, glui32 factor) { + assert(factor); + TimeSeconds ts = TimeAndDate(*date); + return ts / factor; } /* XXX non-official Glk functions that may or may not exist */ diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h index 34531c0829..cf06474481 100644 --- a/engines/gargoyle/glk.h +++ b/engines/gargoyle/glk.h @@ -25,11 +25,11 @@ #include "gargoyle/gargoyle.h" #include "gargoyle/glk_types.h" +#include "gargoyle/time.h" #include "gargoyle/windows.h" namespace Gargoyle { - /** * Implements the GLK interface */ @@ -257,16 +257,14 @@ public: void glk_current_time(glktimeval_t *time); glsi32 glk_current_simple_time(glui32 factor); - void glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date); - void glk_time_to_date_local(glktimeval_t *time, glkdate_t *date); - void glk_simple_time_to_date_utc(glsi32 time, glui32 factor, - glkdate_t *date); - void glk_simple_time_to_date_local(glsi32 time, glui32 factor, - glkdate_t *date); - void glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time); - void glk_date_to_time_local(glkdate_t *date, glktimeval_t *time); - glsi32 glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor); - glsi32 glk_date_to_simple_time_local(glkdate_t *date, glui32 factor); + void glk_time_to_date_utc(const glktimeval_t *time, glkdate_t *date); + void glk_time_to_date_local(const glktimeval_t *time, glkdate_t *date); + void glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date); + void glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date); + void glk_date_to_time_utc(const glkdate_t *date, glktimeval_t *time); + void glk_date_to_time_local(const glkdate_t *date, glktimeval_t *time); + glsi32 glk_date_to_simple_time_utc(const glkdate_t *date, glui32 factor); + glsi32 glk_date_to_simple_time_local(const glkdate_t *date, glui32 factor); #endif /* GLK_MODULE_DATETIME */ diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h index a521548047..274443a9f9 100644 --- a/engines/gargoyle/glk_types.h +++ b/engines/gargoyle/glk_types.h @@ -215,34 +215,11 @@ enum ImageAlign { #endif /* GLK_MODULE_IMAGE */ -#ifdef GLK_MODULE_DATETIME - -struct glktimeval_struct { - glsi32 high_sec; - glui32 low_sec; - glsi32 microsec; -}; -typedef glktimeval_struct glktimeval_t; - -struct glkdate_struct { - glsi32 year; ///< full (four-digit) year */ - glsi32 month; ///< 1-12, 1 is January - glsi32 day; ///< 1-31 - glsi32 weekday; ///< 0-6, 0 is Sunday - glsi32 hour; ///< 0-23 - glsi32 minute; ///< 0-59 - glsi32 second; ///< 0-59, maybe 60 during a leap second - glsi32 microsec; ///< 0-999999 -}; -typedef glkdate_struct glkdate_t; - union gidispatch_rock_t { glui32 num; void *ptr; }; -#endif /* GLK_MODULE_DATETIME */ - } // End of namespace Gargoyle #endif diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk index d3cf7a1592..b8ef788a7e 100644 --- a/engines/gargoyle/module.mk +++ b/engines/gargoyle/module.mk @@ -10,6 +10,7 @@ MODULE_OBJS := \ picture.o \ screen.o \ streams.o \ + time.o \ unicode.o \ unicode_gen.o \ windows.o \ diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp index 1942ddf94d..3ebb98b98f 100644 --- a/engines/gargoyle/streams.cpp +++ b/engines/gargoyle/streams.cpp @@ -156,6 +156,11 @@ void WindowStream::setStyle(glui32 val) { _window->_echoStream->setStyle(val); } +void WindowStream::setHyperlink(glui32 linkVal) { + if (_writable) + _window->_attr.hyper = linkVal; +} + /*--------------------------------------------------------------------------*/ MemoryStream::MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) : diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h index 77ae8cbbf4..de8b704033 100644 --- a/engines/gargoyle/streams.h +++ b/engines/gargoyle/streams.h @@ -153,6 +153,10 @@ public: */ virtual glui32 getLineUni(glui32 *ubuf, glui32 len) { return 0; } + /** + * Set a hyperlink + */ + virtual void setHyperlink(glui32 linkVal) {} }; typedef Stream *strid_t; @@ -195,6 +199,11 @@ public: virtual void putBufferUni(const uint32 *buf, size_t len) override; virtual void setStyle(glui32 val) override; + + /** + * Set a hyperlink + */ + virtual void setHyperlink(glui32 linkVal) override; }; /** diff --git a/engines/gargoyle/time.cpp b/engines/gargoyle/time.cpp new file mode 100644 index 0000000000..9a99d3bfcc --- /dev/null +++ b/engines/gargoyle/time.cpp @@ -0,0 +1,118 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software{} you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation{} either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY{} without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program{} if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gargoyle/time.h" +#include "common/system.h" + +namespace Gargoyle { + +TimeAndDate::TimeAndDate() { + ::TimeDate t; + g_system->getTimeAndDate(t); + + year = t.tm_year; + month = t.tm_mon; + day = t.tm_mday; + weekday = t.tm_wday; + hour = t.tm_hour; + minute = t.tm_min; + second = t.tm_sec; + microsec = 0; +} + +TimeAndDate::TimeAndDate(const TimeSeconds &ts) { + setTime(ts); +} + +TimeAndDate::TimeAndDate(const Timestamp &t) { + setTime(((int64)t.high_sec << 32) | t.low_sec); +} + +TimeAndDate::operator TimeSeconds() const { + return getTime(); +} + +TimeAndDate::operator Timestamp() const { + TimeSeconds secs = getTime(); + Timestamp ts; + ts.high_sec = secs >> 32; + ts.low_sec = secs & 0xffffffff; + ts.microsec = 0; + + return ts; +} + +void TimeAndDate::setTime(const TimeSeconds &ts) { + TimeSeconds total = ts; + int daysInYear, secsInYear; + + // Figure out the year + this->year = 1969; + do { + ++this->year; + daysInYear = ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 365 : 365; + secsInYear = daysInYear * 24 * 60 * 60; + } while (total >= daysInYear); + + // Figure out month and day + int dayInYear = total / (24 * 60 * 60); + total %= 24 * 60 * 60; + + int MONTH_DAYS[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + this->month = 1; + while (dayInYear >= MONTH_DAYS[this->month - 1]) { + dayInYear -= MONTH_DAYS[this->month - 1]; + this->month++; + } + + this->day = dayInYear + 1; + + // set the time within the day + this->hour = total / (60 * 60); + total %= (60 * 60); + this->minute = total / 60; + this->second = total % 60; + this->microsec = 0; +} + +TimeSeconds TimeAndDate::getTime() const { + uint32 days = day - 1; + for (int i = 1970; i < year; ++i) + if ((i % 4 == 0 && i % 100 != 0) || (i % 400 == 0)) + days += 366; + else + days += 365; + + int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + for (int i = 1; i < month; ++i) { + days += mdays[i - 1]; + if (i == 2) + if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) + days += 1; + } + + int64 totalHours = days * 24 + hour; + int64 totalMinutes = totalHours * 60 + minute; + return totalMinutes * 60 + second; +} + +} // End of namespace Gargoyle diff --git a/engines/gargoyle/time.h b/engines/gargoyle/time.h new file mode 100644 index 0000000000..3e658d29f3 --- /dev/null +++ b/engines/gargoyle/time.h @@ -0,0 +1,93 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GARGOYLE_TIME_H +#define GARGOYLE_TIME_H + +#include "gargoyle/glk_types.h" + +namespace Gargoyle { + +typedef int64 TimeSeconds; + +struct Timestamp { + glsi32 high_sec; + glui32 low_sec; + glsi32 microsec; +}; +typedef Timestamp glktimeval_t; + +struct TimeAndDate { + glsi32 year; ///< full (four-digit) year + glsi32 month; ///< 1-12, 1 is January + glsi32 day; ///< 1-31 + glsi32 weekday; ///< 0-6, 0 is Sunday + glsi32 hour; ///< 0-23 + glsi32 minute; ///< 0-59 + glsi32 second; ///< 0-59, maybe 60 during a leap second + glsi32 microsec; ///< 0-999999 +private: + /** + * Get the number of seconds since the start of 1970 + */ + int64 getSecondsSince1970() const; + + /** + * Convert a time in seconds to the structure + */ + void setTime(const TimeSeconds &ts); + + /** + * Get time in seconds from the structure + */ + TimeSeconds getTime() const; +public: + /** + * Constructor + */ + TimeAndDate(); + + /** + * Constructor + */ + TimeAndDate(const TimeSeconds &ts); + + /** + * Constructor + */ + TimeAndDate(const Timestamp &t); + + /** + * Convert to seconds + */ + operator TimeSeconds() const; + + /** + * Convert to time stamp + */ + operator Timestamp() const; +}; +typedef TimeAndDate glkdate_t; + +} // End of namespace Gargoyle + +#endif -- cgit v1.2.3