/* 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 /* * 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); }