executor/src/script.c

971 lines
21 KiB
C

/* Copyright 1991 by Abacus Research and
* Development, Inc. All rights reserved.
*/
/* Forward declarations in ScriptMgr.h (DO NOT DELETE THIS LINE) */
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_script[] =
"$Id: script.c 88 2005-05-25 03:59:37Z ctm $";
#endif
#include "rsys/common.h"
#include "QuickDraw.h"
#include "IntlUtil.h"
#include "ScriptMgr.h"
#include "MemoryMgr.h"
#include "ToolboxUtil.h"
#include "OSUtil.h"
#include "rsys/hook.h"
#include "rsys/quick.h"
#include "rsys/cquick.h"
#include "rsys/osutil.h"
#include "rsys/osevent.h"
#include "rsys/print.h"
#include "rsys/floatconv.h"
#include "rsys/string.h"
#include "rsys/mman.h"
#include <ctype.h>
/*
* NOTE: these are stubs to help me make FileMaker Pro go.
*/
P1(PUBLIC pascal trap, LONGINT, GetEnvirons, INTEGER, verb)
{
LONGINT retval;
switch (verb)
{
case smEnabled:
/* powerpoint seems to require that at least one script is
present */
warning_unimplemented ("reporting script manager is enabled");
/* we currently only have a single script */
retval = 1;
break;
case smKCHRCache:
retval = (LONGINT) US_TO_SYN68K (ROMlib_kchr_ptr ());
break;
default:
warning_unexpected ("unhandled selector `%d'", verb);
retval = 0;
}
return retval;
}
P2(PUBLIC pascal trap, OSErr, SetEnvirons, INTEGER, verb, LONGINT, param)
{
#if defined (BINCOMPAT)
ROMlib_hook(script_notsupported);
#endif /* BINCOMPAT */
return smVerbNotFound;
}
P2(PUBLIC pascal trap, LONGINT, GetScript, INTEGER, script, INTEGER, verb)
{
warning_unimplemented (NULL_STRING);
return 0;
}
P3(PUBLIC pascal trap, OSErr, SetScript, INTEGER, script, INTEGER, verb,
LONGINT, param)
{
warning_unimplemented (NULL_STRING);
return smVerbNotFound;
}
P1(PUBLIC pascal trap, INTEGER, Font2Script, INTEGER, fontnum)
{
warning_unimplemented (NULL_STRING);
return 0;
}
/*
* butchered Transliterate provided for Excel 3.0
*/
#define LOWERTOUPPEROFFSET 'A' - 'a'
A1(PRIVATE, char, upper, char, ch)
{
if (ch >= 'a' && ch <= 'z')
#if 1
return ch + LOWERTOUPPEROFFSET;
#else /* 0 */
return ch & ~0x20;
#endif /* 0 */
else
return ch;
}
#define UPPERTOLOWEROFFSET ('a' - 'A')
A1(PRIVATE, char, lower, char, ch)
{
if (ch >= 'A' && ch <= 'Z')
#if 1
return ch + UPPERTOLOWEROFFSET;
#else /* 0 */
return ch | 0x20;
#endif /* 0 */
else
return ch;
}
P4(PUBLIC pascal trap, INTEGER, Transliterate, Handle, srch, Handle, dsth,
INTEGER, target, LONGINT, srcmask)
{
char *sp, *dp, *ep;
sp = (char *) STARH(srch);
dp = (char *) STARH(dsth);
ep = sp + GetHandleSize(srch);
if (target & smTransLower) {
if (target & smTransUpper)
/*-->*/ return -1;
while (sp < ep)
*dp++ = lower(*sp++);
} else if (target & smTransUpper) {
while (sp < ep)
*dp++ = upper(*sp++);
} else {
while (sp < ep)
*dp++ = *sp++;
}
return 0;
}
/*
* NOTE: These are all recent additions, made just before 1.2.2 was frozen.
* They haven't been tested much, if at all. In addition, much of
* the code below just tries to return something "reasonable", although
* not necessarily correct!
*/
P0(PUBLIC pascal trap, INTEGER, FontScript)
{
warning_unimplemented (NULL_STRING);
return smRoman;
}
P0(PUBLIC pascal trap, INTEGER, IntlScript)
{
warning_unimplemented (NULL_STRING);
return smRoman;
}
P1(PUBLIC pascal trap, void, KeyScript, INTEGER, scriptcode)
{
warning_unimplemented (NULL_STRING);
}
P2(PUBLIC pascal trap, INTEGER, CharType, Ptr, textbufp, INTEGER, offset)
{
INTEGER retval;
unsigned char c;
#if defined (BINCOMPAT)
ROMlib_hook(script_notsupported);
#endif /* BINCOMPAT */
retval = 0;
c = textbufp[offset];
if (!isalpha(c)) {
retval |= smCharPunct;
if (isspace(c))
retval |= smPunctBlank;
else if (isdigit(c))
retval |= smPunctNumber;
else if (ispunct(c))
retval |= smPunctSymbol;
} else {
retval |= smCharAscii;
if (islower(c))
retval |= smCharLower;
else
retval |= smCharUpper;
}
retval |= smCharLeft;
retval |= smChar1byte;
return retval;
}
P4 (PUBLIC pascal trap, void, MeasureJust, Ptr, textbufp, int16, length,
int16, slop, Ptr, charlocs)
{
if (slop)
warning_unimplemented ("slop = %d", slop);
MeasureText (length, textbufp, charlocs);
}
P7 (PUBLIC pascal trap, void, NMeasureJust, Ptr, text, int32, length,
Fixed, slop, Ptr, charLocs, JustStyleCode, run_pos,
Point, numer, Point, denom)
{
Point numerx, denomx;
warning_unimplemented ("slop = %d, run_pos = %d", slop, run_pos);
numerx.v = CW (numer.v);
numerx.h = CW (numer.h);
denomx.v = CW (denomx.v);
denomx.h = CW (denomx.h);
xStdTxMeas (length, (uint8 *) text, &numerx, &denomx,
NULL, (int16 *) charLocs);
}
P1 (PUBLIC pascal trap, Boolean, ParseTable,
CharByteTable, table)
{
memset (table, 0, sizeof (CharByteTable));
return TRUE;
}
P2 (PUBLIC pascal trap, Boolean, FillParseTable,
CharByteTable, table, ScriptCode, script)
{
/* ### should we even look at `script' */
memset (table, 0, sizeof (CharByteTable));
return TRUE;
}
P3 (PUBLIC pascal trap, INTEGER, CharacterByteType, Ptr, textBuf,
INTEGER, textOffset, ScriptCode, script)
{
warning_unimplemented (NULL_STRING);
/* Single-byte character */
return 0;
}
P3 (PUBLIC pascal trap, INTEGER, CharacterType, Ptr, textbufp,
INTEGER, offset, ScriptCode, script)
{
warning_unimplemented (NULL_STRING);
return CharType (textbufp, offset);
}
P5 (PUBLIC pascal trap, INTEGER, TransliterateText, Handle, srch, Handle, dsth,
INTEGER, target, LONGINT, srcmask, ScriptCode, script)
{
warning_unimplemented (NULL_STRING);
return Transliterate (srch, dsth, target, srcmask);
}
P5(PUBLIC pascal trap, INTEGER, Pixel2Char, Ptr, textbufp, INTEGER, len,
INTEGER, slop, INTEGER, pixwidth, BOOLEAN *, leftsidep)
{
Point num, den;
INTEGER retval;
warning_unimplemented ("poorly implemented");
num.h = 1;
num.v = 1;
den.h = 1;
den.v = 1;
retval = C_PixelToChar (textbufp, len, slop << 16, pixwidth << 16, leftsidep,
0, 0, num, den);
return retval;
}
P5(PUBLIC pascal trap, INTEGER, Char2Pixel, Ptr, textbufp, INTEGER, len,
INTEGER, slop, INTEGER, offset, SignedByte, dir)
{
INTEGER retval;
Point num, den;
warning_unimplemented ("poorly implemented");
num.h = 1;
num.v = 1;
den.h = 1;
den.v = 1;
retval = C_CharToPixel (textbufp, len, slop << 16, offset, dir, 0,
num, den);
return retval;
}
P6(PUBLIC pascal trap, void, FindWord, Ptr, textbufp, INTEGER, length,
INTEGER, offset, BOOLEAN, leftside, Ptr, breaks, INTEGER *, offsets)
{
INTEGER start, stop;
boolean_t chasing_spaces_p;
#if defined (BINCOMPAT)
ROMlib_hook(script_notsupported);
#endif /* BINCOMPAT */
if (!leftside)
--offset;
if (offset < 0)
offset = 0;
chasing_spaces_p = isspace (textbufp[offset]);
for (start = offset;
start > 0 && !isspace (textbufp[start-1]) == !chasing_spaces_p;
--start)
;
for (stop = offset;
stop < length && !isspace (textbufp[stop]) == !chasing_spaces_p;
++stop)
;
offsets[0] = CW(start);
offsets[1] = CW(stop);
offsets[2] = 0; /* Testing on Brute shows we should zero this memory */
offsets[3] = 0;
offsets[4] = 0;
offsets[5] = 0;
warning_unimplemented ("poorly implemented");
}
P4(PUBLIC pascal trap, void, HiliteText, Ptr, textbufp, INTEGER, firstoffset,
INTEGER, secondoffset, INTEGER *, offsets)
{
#if defined (BINCOMPAT)
ROMlib_hook(script_notsupported);
#endif /* BINCOMPAT */
offsets[0] = CW(firstoffset);
offsets[1] = CW(secondoffset);
offsets[2] = 0;
offsets[3] = 0;
offsets[4] = 0;
offsets[5] = 0;
}
PRIVATE int16
count_spaces (Ptr textbufp, int16 length)
{
int16 retval;
retval = 0;
while (length-- > 0)
if (*textbufp++ == ' ')
++retval;
return retval;
}
P3 (PUBLIC pascal trap, void, DrawJust, Ptr, textbufp,
int16, length, int16, slop)
{
Fixed save_sp_extra_x;
int n_spaces;
save_sp_extra_x = PORT_SP_EXTRA_X (thePort);
n_spaces = count_spaces (textbufp, length);
if (n_spaces)
{
Fixed extra;
extra = CL (save_sp_extra_x) + FixRatio (slop, n_spaces);
PORT_SP_EXTRA_X (thePort) = CL (extra);
}
DrawText (textbufp, 0, length);
PORT_SP_EXTRA_X (thePort) = save_sp_extra_x;
}
PRIVATE int
snag_date_part (Ptr text, int *offsetp, LONGINT len)
{
int retval;
retval = 0;
while (*offsetp < len && text[*offsetp] != '/')
{
retval = retval * 10 + text[*offsetp] - '0';
++*offsetp;
}
if (*offsetp < len && text[*offsetp] == '/')
++*offsetp;
return retval;
}
enum { longDateFound = 1, dateTimeNotFound = 0x8400 };
P5(PUBLIC pascal trap, String2DateStatus, String2Time, Ptr, textp,
LONGINT, len, Ptr, cachep, LONGINT *, lenusedp, HIDDEN_Ptr *, datetimep)
{
warning_unimplemented (NULL_STRING);
*lenusedp = CLC (0);
return (String2DateStatus) dateTimeNotFound;
}
PRIVATE void
this_date_rec(DateTimeRec *p)
{
LONGINT now;
GetDateTime (&now);
now = CL (now);
Secs2Date (now, p);
}
PRIVATE int
this_century (void)
{
DateTimeRec d;
int retval;
this_date_rec (&d);
retval = CW (d.year) / 100 * 100;
return retval;
}
PRIVATE int
this_millennium (void)
{
int retval;
retval = this_century () / 1000 * 1000;
return retval;
}
P5 (PUBLIC pascal trap, String2DateStatus, String2Date,
Ptr, text, int32, length, DateCachePtr, cache,
int32 *, length_used_ret, LongDatePtr, date_time)
{
String2DateStatus retval;
if (length <= 10 && (text[1] == '/' || text[2] == '/'))
{
int offset, month, day, year;
int offset_save, year_length;
offset = 0;
month = snag_date_part (text, &offset, length);
day = snag_date_part (text, &offset, length);
offset_save = offset;
year = snag_date_part (text, &offset, length);
year_length = offset - offset_save;
if (year_length == 3)
year += this_millennium ();
else if (year_length < 3)
year += this_century ();
*length_used_ret = CL (offset);
/* not clear what we should do with other fields, some should probably
be zeroed */
date_time->year = CW (year);
date_time->month = CW (month);
date_time->day = CW (day);
retval = longDateFound;
}
else
{
*length_used_ret = CLC (0);
warning_unexpected (NULL_STRING);
retval = (String2DateStatus) dateTimeNotFound;
}
warning_unimplemented (NULL_STRING);
return retval;
}
P7 (PUBLIC pascal trap, StyledLineBreakCode, StyledLineBreak,
Ptr, textp, int32, length,
int32, text_start, int32, text_end, int32, flags,
Fixed *, text_width_fp, int32 *, text_offset)
{
char *text = (char *) textp;
/* the index into `text' that began the last word, which is where we
want to break if the current word extends past the end of the
current line */
int last_word_break = -1;
char current_char;
int current_index;
int text_width;
int width = 0;
/* ### are we losing information here? */
text_width = Fix2Long (CL (*text_width_fp));
for (current_index = text_start, current_char = text[current_index];
current_index < text_end;
current_index ++, current_char = text[current_index])
{
/* ### do we do this? */
if (current_char == '\r')
{
*text_offset = CL (current_index + 1);
return smBreakWord;
}
if (current_index > text_start
&& current_char != ' '
&& text[current_index - 1] == ' ')
{
last_word_break = current_index - 1;
}
width += CharWidth (current_char);
if (width > text_width)
{
/* we got our char */
if (last_word_break == -1)
{
/* d'oh, we are on the first word */
if (*text_offset)
{
/* beginning of the line, break here */
*text_offset = CL (current_index - 1);
return smBreakChar;
}
*text_offset = CL (current_index - 1);
return smBreakWord;
}
else
{
*text_offset = CL (last_word_break);
return smBreakWord;
}
}
}
/* if we got here, that means the run did not extend past the end of
the current line */
*text_width_fp = CL (Long2Fix (text_width - width));
*text_offset = CL (current_index);
return smBreakOverflow;
}
P3 (PUBLIC pascal trap, INTEGER, ReplaceText,
Handle, base_text, Handle, subst_text,
Str15, key)
{
INTEGER retval;
warning_unimplemented ("not tested much");
retval = 0;
LOCK_HANDLE_EXCURSION_1
(subst_text,
{
Ptr p;
INTEGER len;
LONGINT offset;
LONGINT l;
p = (Ptr) STARH (subst_text);
len = GetHandleSize (subst_text);
offset = 0;
while (retval >= 0 &&
(l = Munger (base_text,
offset, (Ptr) key+1, key[0], NULL, 1)) >= 0)
{
offset = Munger (base_text,
l, (Ptr) key+1, key[0], p, len);
if (offset < 0)
retval = offset;
else
++retval;
}
});
return retval;
}
/* FormatStr2X is now StringToExtended */
P4 (PUBLIC pascal trap, FormatStatus, StringToExtended, /* TTS TODO */
Str255, string,
NumFormatStringRec *, formatp,
NumberParts *, partsp,
Extended80 *, xp)
{
FormatStatus retval;
double d;
char buf[256];
memcpy (buf, string+1, string[0]);
buf[string[0]] = 0;
sscanf (buf, "%lg", &d);
ieee_to_x80 ((ieee_t) d, xp);
warning_unimplemented (NULL_STRING);
retval = noErr;
return retval;
}
P4 (PUBLIC pascal trap, FormatStatus, ExtendedToString, /* TTS TODO */
Extended80 *, xp,
NumFormatStringRec *, formatp,
NumberParts *, partsp,
Str255, string)
{
ieee_t val;
FormatStatus retval;
char buf[256];
val = x80_to_ieee (xp);
#if !defined (CYGWIN32)
sprintf (buf, "%Lg", val);
#else
#warning may lose bits of precision here
sprintf (buf, "%g", (double) val);
#endif
str255_from_c_string (string ,buf);
warning_unimplemented (NULL_STRING);
retval = noErr;
return retval;
}
P3 (PUBLIC pascal trap, FormatStatus, StringToFormatRec, /* TTS TODO */
Str255, in_string,
NumberParts *, partsp,
NumFormatStringRec *, out_string)
{
FormatStatus retval;
warning_unimplemented (NULL_STRING);
retval = 0;
return retval;
}
P5 (PUBLIC pascal trap, ToggleResults, ToggleDate, /* TTS TODO */
LongDateTime *, lsecsp,
LongDateField, field,
DateDelta, delta,
INTEGER, ch,
TogglePB *, paramsp)
{
ToggleResults retval;
warning_unimplemented (NULL_STRING);
retval = 0;
return retval;
}
P3 (PUBLIC pascal trap, INTEGER, TruncString, /* TTS TODO */
INTEGER, width, Str255, string,
TruncCode, code)
{
warning_unimplemented (NULL_STRING);
/* ### claim we didn't have to truncate the string */
return Truncated;
}
P2 (PUBLIC pascal trap, LONGINT, VisibleLength, Ptr, textp, LONGINT, len)
{
warning_unimplemented ("poorly implemented -- what about other white space");
warning_trace_info ("%.*s", (int) len, textp);
while (len > 0 && textp[len-1] == ' ')
--len;
return len;
}
P2 (PUBLIC pascal trap, void, LongDate2Secs, LongDateRec *, ldatep,
ULONGINT *, secs_outp)
{
long long secs;
LONGINT high, low;
INTEGER hour;
hour = CW (ldatep->hour);
if (ldatep->pm && hour < 12)
hour += 12;
secs = ROMlib_long_long_secs (CW (ldatep->year), CW (ldatep->month),
CW (ldatep->day), hour,
CW (ldatep->minute), CW (ldatep->second));
high = secs >> 32;
low = secs;
secs_outp[0] = CL (high);
secs_outp[1] = CL (low);
}
P2 (PUBLIC pascal trap, void, LongSecs2Date, ULONGINT *, secs_inp,
LongDateRec *, ldatep)
{
long long secs;
INTEGER pm;
secs = ((long long) CL (secs_inp[0]) << 32) | CL (secs_inp[1]);
date_to_swapped_fields (secs, &ldatep->year, &ldatep->month, &ldatep->day,
&ldatep->hour, &ldatep->minute, &ldatep->second,
&ldatep->dayOfWeek, &ldatep->dayOfYear,
&ldatep->weekOfYear);
pm = (CW (ldatep->hour) > 12) ? 1 : 0;
ldatep->pm = CW (pm);
}
/*
* NOTE: At least some of these need to be implemented if we want
* Resolve to work
*/
#if 0
ParseTable
PortionText
FindScriptRun
IsSpecialFont
RawPrinterValues
NPixel2Char
NChar2Pixel
NDrawJust
NPortionText
ReplaceText
TruncText
TrunString
NFindWord
ValidDate
FormatStr2X
FormatX2Str
Format2Str
Str2Format
ToggleDate
LongSecs2Date
LongDate2Secs
IntlTokenize
GetFormatOrder
#endif
A0(PUBLIC, INTEGER, GetAppFont)
{
return CW (ApFontID);
}
#if 0
/*
* NOTE: the following is stuff I typed in before noticing that these are
* provided by glue. Hence they will be necessary if we ever support
* ROMlib again but are not needed for Executor.
*/
A0(PUBLIC, INTEGER, GetDefFontSize)
{
return 0;
}
A0(PUBLIC, INTEGER, GetSysFont)
{
return 0;
}
A0(PUBLIC, INTEGER, GetMBarHeight)
{
return 0;
}
A0(PUBLIC, INTEGER, GetSysJust)
{
return 0;
}
A1(PUBLIC, void, SetSysJust, INTEGER, just)
{
}
#endif
P1 (PUBLIC pascal trap, OSErr, InitDateCache, DateCachePtr, cache) /* TTS TODO */
{
warning_unimplemented (NULL_STRING);
return noErr;
}
P2(PUBLIC pascal trap, INTEGER, CharByte, Ptr, textBuf, INTEGER, textOffset)
{
warning_unimplemented (NULL_STRING);
/* Single-byte character */
return 0;
}
P5(PUBLIC pascal trap, Fixed, PortionLine,
Ptr, textPtr,
LONGINT, textLen,
JustStyleCode, styleRunPosition,
Point, numer,
Point, denom)
{
Fixed retval;
warning_unimplemented (NULL_STRING);
retval = 0x10000;
return retval;
}
P6(PUBLIC pascal trap, void, DrawJustified,
Ptr, textPtr,
LONGINT, textLength,
Fixed, slop,
JustStyleCode, styleRunPosition,
Point, numer,
Point, denom)
{
Point swapped_numer;
Point swapped_denom;
warning_unimplemented ("poorly implemented");
swapped_numer.h = CW (numer.h);
swapped_numer.v = CW (numer.v);
swapped_denom.h = CW (denom.h);
swapped_denom.v = CW (denom.v);
text_helper (textLength, textPtr, &swapped_numer, &swapped_denom, 0, 0,
text_helper_draw);
}
P3(PUBLIC pascal trap, ScriptRunStatus, FindScriptRun,
Ptr, textPtr,
LONGINT, textLen,
LONGINT *, lenUsedp)
{
warning_unimplemented (NULL_STRING);
*lenUsedp = CLC (1);
return 0;
}
P9(PUBLIC pascal trap, INTEGER, PixelToChar,
Ptr, textBuf,
LONGINT, textLen,
Fixed, slop,
Fixed, pixelWidth,
BOOLEAN *, leadingEdgep,
Fixed *, widthRemainingp,
JustStyleCode, styleRunPosition,
Point, numer,
Point, denom)
{
INTEGER *locs;
INTEGER retval, i;
Point swapped_numer;
Point swapped_denom;
INTEGER int_pix_width;
warning_unimplemented ("poorly implemented");
locs = alloca( sizeof(INTEGER) * (textLen + 1));
swapped_numer.h = CW (numer.h);
swapped_numer.v = CW (numer.v);
swapped_denom.h = CW (denom.h);
swapped_denom.v = CW (denom.v);
int_pix_width = pixelWidth >> 16;
text_helper (textLen, textBuf, &swapped_numer, &swapped_denom, 0, locs,
text_helper_measure);
/* NOTE: we could distribute slop here, or we could adjust text_helper
to account for slop (probably better in the long run). Right now,
we do neither. Ick. */
if (int_pix_width >= CW(locs[textLen]))
{
retval = textLen;
*leadingEdgep = FALSE;
*widthRemainingp = pixelWidth - (CW(locs[textLen]) << 16);
}
else
{
*widthRemainingp = CLC (-1);
for (i = 0; int_pix_width > CW(locs[i]); ++i)
;
if ((i > 0) &&
((int_pix_width - CW(locs[i-1])) > (CW(locs[i]) - int_pix_width)))
{
retval = i - 1;
*leadingEdgep = FALSE;
}
else
{
retval = i;
*leadingEdgep = TRUE;
}
}
return retval;
}
P8(PUBLIC pascal trap, INTEGER, CharToPixel,
Ptr, textBuf,
LONGINT, textLen,
Fixed, slop,
LONGINT, offset,
INTEGER, direction,
JustStyleCode, styleRunPosition,
Point, numer,
Point, denom)
{
INTEGER retval;
Point swapped_numer, swapped_denom;
warning_unimplemented ("poorly implemented");
swapped_numer.h = CW (numer.h);
swapped_numer.v = CW (numer.v);
swapped_denom.h = CW (denom.h);
swapped_denom.v = CW (denom.v);
retval = text_helper (offset, textBuf, &swapped_numer, &swapped_denom,
0, 0, text_helper_measure);
retval += (slop / textLen) >> 16;
return retval;
}
P3(PUBLIC pascal trap, void, LowercaseText,
Ptr, textp,
INTEGER, len,
ScriptCode, script)
{
warning_unimplemented ("poorly implemented");
}
P3(PUBLIC pascal trap, void, UppercaseText,
Ptr, textp,
INTEGER, len,
ScriptCode, script)
{
ROMlib_UprString ((StringPtr) textp, FALSE, len);
}
P3(PUBLIC pascal trap, void, StripDiacritics,
Ptr, textp,
INTEGER, len,
ScriptCode, script)
{
warning_unimplemented ("poorly implemented");
}
P3(PUBLIC pascal trap, void, UppercaseStripDiacritics,
Ptr, textp,
INTEGER, len,
ScriptCode, script)
{
ROMlib_UprString ((StringPtr) textp, TRUE, len);
}