2015-02-02 22:02:57 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2015, Kelvin W Sherlock
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
2015-02-18 14:32:01 +00:00
|
|
|
* modification, are permitted provided that the following conditions are met:
|
2015-02-02 22:02:57 +00:00
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
2015-02-18 14:32:01 +00:00
|
|
|
* list of conditions and the following disclaimer.
|
2015-02-02 22:02:57 +00:00
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer in the documentation
|
2015-02-18 14:32:01 +00:00
|
|
|
* and/or other materials provided with the distribution.
|
2015-02-02 22:02:57 +00:00
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <cerrno>
|
|
|
|
#include <cctype>
|
|
|
|
#include <ctime>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <chrono>
|
|
|
|
#include <deque>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <cpu/defs.h>
|
|
|
|
#include <cpu/CpuModule.h>
|
|
|
|
#include <cpu/fmem.h>
|
|
|
|
|
|
|
|
#include <macos/sysequ.h>
|
|
|
|
#include <macos/errors.h>
|
|
|
|
#include <macos/traps.h>
|
|
|
|
|
|
|
|
#include "toolbox.h"
|
|
|
|
#include "stackframe.h"
|
|
|
|
#include "os.h"
|
|
|
|
#include "packages.h"
|
|
|
|
|
|
|
|
using ToolBox::Log;
|
|
|
|
using OS::MacToUnix;
|
|
|
|
|
|
|
|
namespace Packages {
|
|
|
|
|
2020-07-14 02:52:44 +00:00
|
|
|
enum {
|
|
|
|
shortDate = 0,
|
|
|
|
longDate = 1,
|
|
|
|
abbrevDate = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
mdy = 0,
|
|
|
|
dmy = 1,
|
|
|
|
ymd = 2,
|
|
|
|
myd = 3,
|
|
|
|
dym = 4,
|
|
|
|
ydm = 5
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
timeCycle24 = 0, /*time sequence 0:00 - 23:59*/
|
|
|
|
timeCycleZero = 1, /*time sequence 0:00-11:59, 0:00 - 11:59*/
|
|
|
|
timeCycle12 = 255, /*time sequence 12:00 - 11:59, 12:00 - 11:59*/
|
|
|
|
zeroCycle = 1, /*old name for timeCycleZero*/
|
|
|
|
longDay = 0, /*day of the month*/
|
|
|
|
longWeek = 1, /*day of the week*/
|
|
|
|
longMonth = 2, /*month of the year*/
|
|
|
|
longYear = 3, /*year*/
|
|
|
|
supDay = 1, /*suppress day of month*/
|
|
|
|
supWeek = 2, /*suppress day of week*/
|
|
|
|
supMonth = 4, /*suppress month*/
|
|
|
|
supYear = 8, /*suppress year*/
|
|
|
|
|
|
|
|
dayLdingZ = 32,
|
|
|
|
mntLdingZ = 64,
|
|
|
|
century = 128,
|
|
|
|
secLeadingZ = 32,
|
|
|
|
minLeadingZ = 64,
|
|
|
|
hrLeadingZ = 128
|
|
|
|
};
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
struct Intl0Rec {
|
|
|
|
char decimalPt; /*decimal point character*/
|
|
|
|
char thousSep; /*thousands separator character*/
|
|
|
|
char listSep; /*list separator character*/
|
|
|
|
char currSym1; /*currency symbol*/
|
|
|
|
char currSym2;
|
|
|
|
char currSym3;
|
|
|
|
UInt8 currFmt; /*currency format flags*/
|
|
|
|
UInt8 dateOrder; /*order of short date elements: mdy, dmy, etc.*/
|
|
|
|
UInt8 shrtDateFmt; /*format flags for each short date element*/
|
|
|
|
char dateSep; /*date separator character*/
|
|
|
|
UInt8 timeCycle; /*specifies time cycle: 0..23, 1..12, or 0..11*/
|
|
|
|
UInt8 timeFmt; /*format flags for each time element*/
|
|
|
|
char mornStr[4]; /*trailing string for AM if 12-hour cycle*/
|
|
|
|
char eveStr[4]; /*trailing string for PM if 12-hour cycle*/
|
|
|
|
char timeSep; /*time separator character*/
|
|
|
|
char time1Suff; /*trailing string for AM if 24-hour cycle*/
|
|
|
|
char time2Suff;
|
|
|
|
char time3Suff;
|
|
|
|
char time4Suff;
|
|
|
|
char time5Suff; /*trailing string for PM if 24-hour cycle*/
|
|
|
|
char time6Suff;
|
|
|
|
char time7Suff;
|
|
|
|
char time8Suff;
|
|
|
|
UInt8 metricSys; /*255 if metric, 0 if inches etc.*/
|
|
|
|
short intl0Vers; /*region code (hi byte) and version (lo byte)*/
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
enum {
|
|
|
|
o_decimalPt = 0,
|
|
|
|
o_thousSep = 1,
|
|
|
|
o_listSep = 2,
|
|
|
|
o_currSym1 = 3,
|
|
|
|
o_currSym2 = 4,
|
|
|
|
o_currSym3 = 5,
|
|
|
|
o_currFmt = 6,
|
|
|
|
o_dateOrder = 7,
|
|
|
|
o_shrtDateFmt = 8,
|
|
|
|
o_dateSep = 9,
|
|
|
|
o_timeCycle = 10,
|
|
|
|
o_timeFmt = 11,
|
|
|
|
o_mornStr = 12,
|
|
|
|
o_eveStr = 16,
|
|
|
|
o_timeSep = 20,
|
|
|
|
o_time1Suff = 21,
|
|
|
|
o_time2Suff = 22,
|
|
|
|
o_time3Suff = 23,
|
|
|
|
o_time4Suff = 24,
|
|
|
|
o_time5Suff = 25,
|
|
|
|
o_time6Suff = 26,
|
|
|
|
o_time7Suff = 27,
|
|
|
|
o_time8Suff = 28,
|
|
|
|
o_metricSys = 29,
|
|
|
|
o_intl0Vers = 30, /* 16-bit */
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DateFormat {
|
|
|
|
uint8_t dateOrder = mdy;
|
|
|
|
uint8_t dateSep = '/';
|
|
|
|
uint8_t shrtDateFmt = 0;
|
|
|
|
|
|
|
|
void unpack(uint32_t intlPtr) {
|
|
|
|
if (!intlPtr) return;
|
|
|
|
|
|
|
|
dateOrder = memoryReadByte(intlPtr + o_dateOrder);
|
|
|
|
shrtDateFmt = memoryReadByte(intlPtr + o_shrtDateFmt);
|
|
|
|
dateSep = memoryReadByte(intlPtr + o_dateSep);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct TimeFormat {
|
|
|
|
uint8_t timeCycle = timeCycle12;
|
|
|
|
uint8_t timeSep = ':';
|
|
|
|
uint8_t timeFmt = secLeadingZ + minLeadingZ;
|
|
|
|
|
|
|
|
std::string mornStr = " AM";
|
|
|
|
std::string eveStr = " PM";
|
|
|
|
|
|
|
|
void unpack(uint32_t intlPtr) {
|
|
|
|
if (!intlPtr) return;
|
|
|
|
|
|
|
|
timeCycle = memoryReadByte(intlPtr + o_timeCycle);
|
|
|
|
timeFmt = memoryReadByte(intlPtr + o_timeFmt);
|
|
|
|
timeSep = memoryReadByte(intlPtr + o_timeSep);
|
|
|
|
|
|
|
|
if (timeCycle == timeCycle24) {
|
|
|
|
mornStr = read_string(intlPtr + o_time1Suff);
|
|
|
|
eveStr = read_string(intlPtr + o_time5Suff);
|
|
|
|
} else {
|
|
|
|
mornStr = read_string(intlPtr + o_mornStr);
|
|
|
|
eveStr = read_string(intlPtr + o_eveStr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::string read_string(uint32_t address) {
|
|
|
|
std::string rv;
|
|
|
|
for (unsigned i = 0; i < 4; ++i, ++address) {
|
|
|
|
char c = memoryReadByte(address);
|
|
|
|
if (!c) break;
|
|
|
|
rv.push_back(c);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
std::string FormatAbbrDate(uint32_t dateTime, uint32_t intlPtr) {
|
|
|
|
std::string rv;
|
|
|
|
|
|
|
|
char dd[8];
|
|
|
|
char mm[8];
|
|
|
|
char yy[8];
|
|
|
|
|
|
|
|
std::string sep;
|
|
|
|
|
|
|
|
DateFormat df;
|
|
|
|
|
|
|
|
time_t t = MacToUnix(dateTime);
|
|
|
|
struct tm *tm = ::localtime(&t);
|
|
|
|
|
|
|
|
if (intlPtr) df.unpack(intlPtr);
|
|
|
|
if (df.dateSep) sep.push_back(df.dateSep);
|
|
|
|
|
|
|
|
if (df.shrtDateFmt & dayLdingZ) snprintf(dd, sizeof(dd), "%02u", tm->tm_mday);
|
|
|
|
else snprintf(dd, sizeof(dd), "%u", tm->tm_mday);
|
|
|
|
|
|
|
|
if (df.shrtDateFmt & mntLdingZ) snprintf(mm, sizeof(mm), "%02u", tm->tm_mon + 1);
|
|
|
|
else snprintf(mm, sizeof(mm), "%u", tm->tm_mon + 1);
|
|
|
|
|
|
|
|
if (df.shrtDateFmt & century) snprintf(yy, sizeof(yy), "%04u", tm->tm_year + 1900);
|
|
|
|
else snprintf(yy, sizeof(yy), "%02u", tm->tm_year % 100);
|
|
|
|
|
|
|
|
|
|
|
|
switch(df.dateOrder) {
|
|
|
|
default:
|
|
|
|
case mdy:
|
|
|
|
rv = mm + sep + dd + sep + yy;
|
|
|
|
break;
|
|
|
|
case dmy:
|
|
|
|
rv = dd + sep + mm + sep + yy;
|
|
|
|
break;
|
|
|
|
case ymd:
|
|
|
|
rv = yy + sep + mm + sep + dd;
|
|
|
|
break;
|
|
|
|
case myd:
|
|
|
|
rv = mm + sep + yy + sep + dd;
|
|
|
|
break;
|
|
|
|
case dym:
|
|
|
|
rv = dd + sep + yy + sep + mm;
|
|
|
|
break;
|
|
|
|
case ydm:
|
|
|
|
rv = yy + sep + dd + sep + mm;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string FormatDate(uint32_t dateTime, unsigned form, uint32_t intlPtr) {
|
|
|
|
/* not localized. some foreign day/month strings include macroman chars */
|
|
|
|
|
|
|
|
if (form == abbrevDate)
|
|
|
|
return FormatAbbrDate(dateTime, intlPtr);
|
|
|
|
|
|
|
|
char buffer[256];
|
|
|
|
int length;
|
|
|
|
std::string rv;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
time_t t = MacToUnix(dateTime);
|
|
|
|
struct tm *tm = ::localtime(&t);
|
|
|
|
|
|
|
|
|
|
|
|
switch(form) {
|
|
|
|
case shortDate:
|
|
|
|
// Sat, Jul 11, 2020
|
|
|
|
// length = std::strftime(buffer, sizeof(buffer), "%a, %b %e, %Y", tm);
|
|
|
|
length = std::strftime(buffer, sizeof(buffer), "%a, %b ", tm);
|
|
|
|
rv = std::string(buffer, buffer + length);
|
|
|
|
length = std::snprintf(buffer, sizeof(buffer), "%u, %04u",
|
|
|
|
tm->tm_mday, tm->tm_year + 1900);
|
|
|
|
rv.append(buffer, buffer + length);
|
|
|
|
break;
|
|
|
|
case longDate:
|
|
|
|
default:
|
|
|
|
// Saturday, July 11, 2020
|
|
|
|
// length = std::strftime(buffer, sizeof(buffer), "%A, %B %e, %Y", tm);
|
|
|
|
length = std::strftime(buffer, sizeof(buffer), "%A, %B ", tm);
|
|
|
|
rv = std::string(buffer, buffer + length);
|
|
|
|
length = std::snprintf(buffer, sizeof(buffer), "%u, %04u",
|
|
|
|
tm->tm_mday, tm->tm_year + 1900);
|
|
|
|
rv.append(buffer, buffer + length);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string FormatTime(uint32_t dateTime, bool seconds, uint32_t intlPtr) {
|
|
|
|
|
|
|
|
char hh[8];
|
|
|
|
char mm[8];
|
|
|
|
char ss[8];
|
|
|
|
|
|
|
|
std::string rv;
|
|
|
|
|
|
|
|
std::string sep;
|
|
|
|
|
|
|
|
TimeFormat tf;
|
|
|
|
|
|
|
|
time_t t = MacToUnix(dateTime);
|
|
|
|
struct tm *tm = ::localtime(&t);
|
|
|
|
|
|
|
|
if (intlPtr) tf.unpack(intlPtr);
|
|
|
|
if (tf.timeSep) sep.push_back(tf.timeSep);
|
|
|
|
|
|
|
|
|
|
|
|
if (tf.timeFmt & secLeadingZ) snprintf(ss, sizeof(ss), "%02u", tm->tm_sec);
|
|
|
|
else snprintf(ss, sizeof(ss), "%u", tm->tm_sec);
|
|
|
|
|
|
|
|
if (tf.timeFmt & minLeadingZ) snprintf(mm, sizeof(mm), "%02u", tm->tm_min);
|
|
|
|
else snprintf(mm, sizeof(mm), "%u", tm->tm_min);
|
|
|
|
|
|
|
|
|
|
|
|
unsigned h = tm->tm_hour;
|
|
|
|
bool am = h < 12;
|
|
|
|
switch (tf.timeCycle) {
|
|
|
|
default:
|
|
|
|
case timeCycle12:
|
|
|
|
h %= 12;
|
|
|
|
if (!h) h = 12;
|
|
|
|
break;
|
|
|
|
case timeCycle24:
|
|
|
|
break;
|
|
|
|
case timeCycleZero:
|
|
|
|
h %= 12;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tf.timeFmt & hrLeadingZ) snprintf(hh, sizeof(hh), "%02u", h);
|
|
|
|
else snprintf(hh, sizeof(hh), "%u", h);
|
|
|
|
|
|
|
|
|
|
|
|
rv = hh + sep + mm;
|
|
|
|
if (seconds) {
|
|
|
|
rv += sep + ss;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv.append( am ? tf.mornStr : tf.eveStr);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2015-02-02 22:02:57 +00:00
|
|
|
|
|
|
|
uint16_t IUDateString()
|
|
|
|
{
|
2020-07-14 02:52:44 +00:00
|
|
|
// void IUDateString(long dateTime, DateForm longFlag, Str255 result)
|
2015-02-02 22:02:57 +00:00
|
|
|
|
|
|
|
std::string out;
|
|
|
|
|
|
|
|
uint32_t dateTime;
|
|
|
|
uint8_t flag;
|
|
|
|
uint32_t result;
|
|
|
|
|
|
|
|
|
|
|
|
StackFrame<10>(dateTime, flag, result);
|
|
|
|
|
|
|
|
Log(" IUDateString(%08x, %02x, %08x)\n", dateTime, flag, result);
|
|
|
|
|
2020-07-14 02:52:44 +00:00
|
|
|
out = FormatDate(dateTime, flag, 0);
|
|
|
|
ToolBox::WritePString(result, out);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t IUDatePString()
|
|
|
|
{
|
|
|
|
// void IUDateString(long dateTime, DateForm longFlag, Str255 result, Handle intlHandle)
|
|
|
|
|
|
|
|
std::string out;
|
|
|
|
|
|
|
|
uint32_t dateTime;
|
|
|
|
uint8_t flag;
|
|
|
|
uint32_t result;
|
|
|
|
uint32_t intlHandle;
|
|
|
|
uint32_t intlPtr;
|
2015-02-02 22:02:57 +00:00
|
|
|
|
|
|
|
|
2020-07-14 02:52:44 +00:00
|
|
|
StackFrame<14>(dateTime, flag, result, intlHandle);
|
|
|
|
|
|
|
|
Log(" IUDatePString(%08x, %02x, %08x, %08x)\n", dateTime, flag, result, intlHandle);
|
|
|
|
|
|
|
|
intlPtr = intlHandle ? memoryReadLong(intlHandle) : 0;
|
|
|
|
|
|
|
|
out = FormatDate(dateTime, flag, intlPtr);
|
2015-02-02 22:02:57 +00:00
|
|
|
ToolBox::WritePString(result, out);
|
|
|
|
return 0;
|
2020-07-14 02:52:44 +00:00
|
|
|
|
2015-02-02 22:02:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t IUTimeString()
|
|
|
|
{
|
|
|
|
// void IUTimeString(long dateTime,Boolean wantSeconds,Str255 result)
|
|
|
|
// output: 12:00:00 AM or 12:00 AM
|
|
|
|
|
|
|
|
std::string out;
|
|
|
|
|
|
|
|
uint32_t dateTime;
|
|
|
|
uint8_t wantSeconds;
|
|
|
|
uint32_t result;
|
|
|
|
|
|
|
|
|
|
|
|
StackFrame<10>(dateTime, wantSeconds, result);
|
|
|
|
Log(" IUTimeString(%08x, %02x, %08x)\n", dateTime, wantSeconds, result);
|
|
|
|
|
2020-07-14 02:52:44 +00:00
|
|
|
out = FormatTime(dateTime, wantSeconds, 0);
|
|
|
|
|
|
|
|
ToolBox::WritePString(result, out);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t IUTimePString() {
|
|
|
|
// void IUTimePString(long dateTime, Boolean wantSeconds, Str255 result, Handle intlHandle)
|
|
|
|
|
|
|
|
|
|
|
|
std::string out;
|
2015-02-02 22:02:57 +00:00
|
|
|
|
2020-07-14 02:52:44 +00:00
|
|
|
uint32_t dateTime;
|
|
|
|
uint8_t wantSeconds;
|
|
|
|
uint32_t result;
|
|
|
|
uint32_t intlHandle;
|
|
|
|
uint32_t intlPtr;
|
2015-02-02 22:02:57 +00:00
|
|
|
|
2020-07-14 02:52:44 +00:00
|
|
|
StackFrame<14>(dateTime, wantSeconds, result, intlHandle);
|
|
|
|
Log(" IUTimePString(%08x, %02x, %08x, %08x)\n", dateTime, wantSeconds, result, intlHandle);
|
2015-02-02 22:02:57 +00:00
|
|
|
|
2020-07-14 02:52:44 +00:00
|
|
|
intlPtr = intlHandle ? memoryReadLong(intlHandle) : 0;
|
|
|
|
|
|
|
|
out = FormatTime(dateTime, wantSeconds, intlPtr);
|
2015-02-02 22:02:57 +00:00
|
|
|
ToolBox::WritePString(result, out);
|
2015-02-18 14:32:01 +00:00
|
|
|
return 0;
|
2015-02-02 22:02:57 +00:00
|
|
|
}
|
|
|
|
|
2020-07-14 02:52:44 +00:00
|
|
|
uint16_t InitDateCache()
|
|
|
|
{
|
|
|
|
// OSErr InitDateCache(DateCachePtr theCache)
|
|
|
|
uint32_t theCache;
|
|
|
|
uint32_t sp;
|
|
|
|
sp = StackFrame<4>(theCache);
|
|
|
|
Log(" InitDateCache(%08x)\n", theCache);
|
|
|
|
/* cache not used */
|
|
|
|
|
|
|
|
ToolReturn<4>(sp, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum {
|
|
|
|
/* StringToDate status values */
|
|
|
|
fatalDateTime = 0x8000, /* StringToDate and String2Time mask to a fatal error */
|
|
|
|
longDateFound = 1, /* StringToDate mask to long date found */
|
|
|
|
leftOverChars = 2, /* StringToDate & Time mask to warn of left over characters */
|
|
|
|
sepNotIntlSep = 4, /* StringToDate & Time mask to warn of non-standard separators */
|
|
|
|
fieldOrderNotIntl = 8, /* StringToDate & Time mask to warn of non-standard field order */
|
|
|
|
extraneousStrings = 16, /* StringToDate & Time mask to warn of unparsable strings in text */
|
|
|
|
tooManySeps = 32, /* StringToDate & Time mask to warn of too many separators */
|
|
|
|
sepNotConsistent = 64, /* StringToDate & Time mask to warn of inconsistent separators */
|
|
|
|
tokenErr = 0x8100, /* StringToDate & Time mask for 'tokenizer err encountered' */
|
|
|
|
cantReadUtilities = 0x8200,
|
|
|
|
dateTimeNotFound = 0x8400,
|
|
|
|
dateTimeInvalid = 0x8800
|
|
|
|
};
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
typedef short StringToDateStatus;
|
|
|
|
typedef StringToDateStatus String2DateStatus;
|
|
|
|
struct DateCacheRecord {
|
|
|
|
short hidden[256]; /* only for temporary use */
|
|
|
|
};
|
|
|
|
typedef struct DateCacheRecord DateCacheRecord;
|
|
|
|
typedef DateCacheRecord * DateCachePtr;
|
|
|
|
struct DateTimeRec {
|
|
|
|
short year;
|
|
|
|
short month;
|
|
|
|
short day;
|
|
|
|
short hour;
|
|
|
|
short minute;
|
|
|
|
short second;
|
|
|
|
short dayOfWeek;
|
|
|
|
};
|
|
|
|
typedef struct DateTimeRec DateTimeRec;
|
|
|
|
|
|
|
|
typedef SInt64 LongDateTime;
|
|
|
|
union LongDateCvt {
|
|
|
|
SInt64 c;
|
|
|
|
struct {
|
|
|
|
UInt32 lHigh;
|
|
|
|
UInt32 lLow;
|
|
|
|
} hl;
|
|
|
|
};
|
|
|
|
typedef union LongDateCvt LongDateCvt;
|
|
|
|
union LongDateRec {
|
|
|
|
struct {
|
|
|
|
short era;
|
|
|
|
short year;
|
|
|
|
short month;
|
|
|
|
short day;
|
|
|
|
short hour;
|
|
|
|
short minute;
|
|
|
|
short second;
|
|
|
|
short dayOfWeek;
|
|
|
|
short dayOfYear;
|
|
|
|
short weekOfYear;
|
|
|
|
short pm;
|
|
|
|
short res1;
|
|
|
|
short res2;
|
|
|
|
short res3;
|
|
|
|
} ld;
|
|
|
|
short list[14]; /*Index by LongDateField!*/
|
|
|
|
struct {
|
|
|
|
short eraAlt;
|
|
|
|
DateTimeRec oldDate;
|
|
|
|
} od;
|
|
|
|
};
|
|
|
|
typedef union LongDateRec LongDateRec;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
|
|
|
o_era = 0, /* 0 = AD, -1 = BC */
|
|
|
|
o_year = 2,
|
|
|
|
o_month = 4, /* 1-12 */
|
|
|
|
o_day = 6, /* 1-31 */
|
|
|
|
o_hour = 8,
|
|
|
|
o_minute = 10,
|
|
|
|
o_second = 12,
|
|
|
|
o_dayOfWeek = 14, /*1-7, sun-sat */
|
|
|
|
o_dayOfYear = 16, /* 1-365 (366) */
|
|
|
|
o_weekOfYear = 18, /* 1- 52 */
|
|
|
|
o_pm = 20, /* 0 = am, 1 = pm */
|
|
|
|
o_res1 = 22,
|
|
|
|
o_res2 = 24,
|
|
|
|
o_res3 = 26,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint16_t StringToDate()
|
|
|
|
{
|
|
|
|
// StringToDateStatus StringToDate(Ptr textPtr, long textLen, DateCachePtr theCache, long *lengthUsed, LongDateRec *dateTime)
|
|
|
|
uint32_t sp;
|
|
|
|
uint32_t textPtr;
|
|
|
|
uint32_t textLen;
|
|
|
|
uint32_t theCache;
|
|
|
|
uint32_t lengthUsed;
|
|
|
|
uint32_t dateTime;
|
|
|
|
|
|
|
|
uint16_t rv = 0;
|
|
|
|
uint32_t used = 0;
|
|
|
|
|
|
|
|
struct tm tm = {};
|
|
|
|
|
|
|
|
sp = StackFrame<20>(textPtr, textLen, theCache, lengthUsed, dateTime);
|
|
|
|
std::string s = ToolBox::ReadString(textPtr, textLen);
|
|
|
|
|
|
|
|
Log(" StringToDate(%s, %08lx)\n", s.c_str(), dateTime);
|
|
|
|
|
|
|
|
rv = dateTimeNotFound;
|
|
|
|
if (s.length()) {
|
|
|
|
/* only allow %Y-%m-%d for now */
|
|
|
|
char *cp;
|
|
|
|
cp = strptime(s.c_str(), " %Y-%m-%d", &tm);
|
|
|
|
if (!cp) cp = strptime(s.c_str(), "%m/%d/%Y", &tm);
|
|
|
|
|
|
|
|
if (cp) {
|
|
|
|
rv = longDateFound;
|
|
|
|
used = cp - s.c_str();
|
|
|
|
|
|
|
|
memoryWriteWord(0, dateTime+o_era); /* o = AD, -1 = BC */
|
|
|
|
memoryWriteWord(1900 + tm.tm_year, dateTime+o_year);
|
|
|
|
memoryWriteWord(1 + tm.tm_mon, dateTime+o_month);
|
|
|
|
memoryWriteWord(0 + tm.tm_mday, dateTime+o_day);
|
|
|
|
/* not populated */
|
|
|
|
//memoryWriteWord(1 + tm.tm_wday, dateTime+o_dayOfWeek);
|
|
|
|
//memoryWriteWord(1 + tm.tm_yday, dateTime+o_dayOfYear);
|
|
|
|
// unsupported - week of year....
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
memoryWriteLong(used, lengthUsed);
|
|
|
|
ToolReturn<2>(sp, rv);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t StringToTime()
|
|
|
|
{
|
|
|
|
// StringToDateStatus StringToTime(Ptr textPtr, long textLen, DateCachePtr theCache, long *lengthUsed, LongDateRec *dateTime)
|
|
|
|
uint32_t sp;
|
|
|
|
uint32_t textPtr;
|
|
|
|
uint32_t textLen;
|
|
|
|
uint32_t theCache;
|
|
|
|
uint32_t lengthUsed;
|
|
|
|
uint32_t dateTime;
|
|
|
|
|
|
|
|
uint16_t rv = 0;
|
|
|
|
uint32_t used = 0;
|
|
|
|
|
|
|
|
sp = StackFrame<20>(textPtr, textLen, theCache, lengthUsed, dateTime);
|
|
|
|
std::string s = ToolBox::ReadString(textPtr, textLen);
|
|
|
|
|
|
|
|
Log(" StringToTime(%s, %08lx)\n", s.c_str(), dateTime);
|
|
|
|
|
|
|
|
|
|
|
|
rv = dateTimeNotFound;
|
|
|
|
|
|
|
|
memoryWriteLong(used, lengthUsed);
|
|
|
|
ToolReturn<2>(sp, rv);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-02-02 22:02:57 +00:00
|
|
|
uint16_t GetIntlResource()
|
|
|
|
{
|
|
|
|
// FUNCTION GetIntlResource (theID: Integer) :Handle;
|
|
|
|
|
|
|
|
// todo -- actually load the resource
|
|
|
|
|
|
|
|
/*
|
|
|
|
* theID Contains an integer (0, 1, 2, 4, or 5 respectively for
|
|
|
|
* the 'itl0', 'itl1', 'itl2', 'itl4', and 'itl5'resources) to
|
|
|
|
* identify the type of the desired international resource.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t theID;
|
|
|
|
|
|
|
|
uint32_t sp = StackFrame<2>(theID);
|
|
|
|
|
|
|
|
Log(" GetIntlResource(%04x)\n", theID);
|
|
|
|
|
|
|
|
ToolReturn<4>(sp, 0);
|
|
|
|
return 0; // should set res error.
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t Pack6(uint16_t trap)
|
|
|
|
{
|
|
|
|
|
|
|
|
uint16_t selector;
|
|
|
|
StackFrame<2>(selector);
|
|
|
|
|
|
|
|
Log("%04x Pack6(%04x)\n", trap, selector);
|
|
|
|
|
|
|
|
switch(selector)
|
|
|
|
{
|
|
|
|
case 0x0000:
|
|
|
|
return IUDateString();
|
|
|
|
case 0x0002:
|
|
|
|
return IUTimeString();
|
2020-07-14 02:52:44 +00:00
|
|
|
// case 0x0004: return IsMetric();
|
2015-02-02 22:02:57 +00:00
|
|
|
case 0x0006:
|
|
|
|
return GetIntlResource();
|
2020-07-14 02:52:44 +00:00
|
|
|
// case 0x0008: return SetIntlResource();
|
|
|
|
case 0x000e:
|
|
|
|
return IUDatePString();
|
|
|
|
case 0x0010:
|
|
|
|
return IUTimePString();
|
2015-02-02 22:02:57 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "Pack6: selector %04x not supported\n", selector);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-14 02:52:44 +00:00
|
|
|
uint16_t ScriptUtil(uint16_t trap)
|
|
|
|
{
|
|
|
|
uint32_t selector;
|
|
|
|
StackFrame<4>(selector);
|
|
|
|
Log("%04x ScriptUtil(%08x)\n", trap, selector);
|
|
|
|
|
|
|
|
switch(selector)
|
|
|
|
{
|
|
|
|
case 0x8204fff8:
|
|
|
|
return InitDateCache();
|
|
|
|
case 0x8214fff6:
|
|
|
|
return StringToDate();
|
|
|
|
case 0x8214fff4:
|
|
|
|
return StringToTime();
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "ScriptUtil: selector %08x not supported\n", selector);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-02-02 22:02:57 +00:00
|
|
|
}
|