X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/10135a55c1d5f8d55ae5edbcd5544f676c83a693..fabd1805a8f429ca83b4271aabd1206ac3537ebb:/mac/macterm.c diff --git a/mac/macterm.c b/mac/macterm.c index 89215177..02232a57 100644 --- a/mac/macterm.c +++ b/mac/macterm.c @@ -1,4 +1,4 @@ -/* $Id: macterm.c,v 1.7 2002/11/23 14:22:11 ben Exp $ */ +/* $Id: macterm.c,v 1.50 2003/01/15 23:30:21 ben Exp $ */ /* * Copyright (c) 1999 Simon Tatham * Copyright (c) 1999, 2002 Ben Harris @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -45,8 +46,11 @@ #include #include #include +#include +#include #include #include +#include #include #include @@ -56,7 +60,9 @@ #include "macresid.h" #include "putty.h" +#include "charset.h" #include "mac.h" +#include "storage.h" #include "terminal.h" #define NCOLOURS (lenof(((Config *)0)->colours)) @@ -74,13 +80,17 @@ (y) / s->font_height) static void mac_initfont(Session *); +static pascal OSStatus uni_to_font_fallback(UniChar *, ByteCount, ByteCount *, + TextPtr, ByteCount, ByteCount *, + LogicalAddress *, + ConstUnicodeMappingPtr); static void mac_initpalette(Session *); static void mac_adjustwinbg(Session *); static void mac_adjustsize(Session *, int, int); static void mac_drawgrowicon(Session *s); +static pascal void mac_growtermdraghook(void); static pascal void mac_scrolltracker(ControlHandle, short); static pascal void do_text_for_device(short, short, GDHandle, long); -static pascal void mac_set_attr_mask(short, short, GDHandle, long); static int mac_keytrans(Session *, EventRecord *, unsigned char *); static void text_click(Session *, EventRecord *); @@ -94,57 +104,55 @@ static RoutineDescriptor mac_scrolltracker_upp = static RoutineDescriptor do_text_for_device_upp = BUILD_ROUTINE_DESCRIPTOR(uppDeviceLoopDrawingProcInfo, (ProcPtr)do_text_for_device); -static RoutineDescriptor mac_set_attr_mask_upp = - BUILD_ROUTINE_DESCRIPTOR(uppDeviceLoopDrawingProcInfo, - (ProcPtr)mac_set_attr_mask); #else /* not TARGET_RT_MAC_CFM */ #define mac_scrolltracker_upp mac_scrolltracker #define do_text_for_device_upp do_text_for_device -#define mac_set_attr_mask_upp mac_set_attr_mask #endif /* not TARGET_RT_MAC_CFM */ -static void inbuf_putc(Session *s, int c) { - char ch = c; +void mac_opensession(void) { + Session *s; + StandardFileReply sfr; + static const OSType sftypes[] = { 'Sess', 0, 0, 0 }; + void *sesshandle; + int i; - from_backend(s->term, 0, &ch, 1); -} + s = smalloc(sizeof(*s)); + memset(s, 0, sizeof(*s)); -static void inbuf_putstr(Session *s, const char *c) { + StandardGetFile(NULL, 1, sftypes, &sfr); + if (!sfr.sfGood) goto fail; - from_backend(s->term, 0, (char *)c, strlen(c)); -} + sesshandle = open_settings_r_fsp(&sfr.sfFile); + if (sesshandle == NULL) goto fail; + load_open_settings(sesshandle, TRUE, &s->cfg); + close_settings_r(sesshandle); -static void display_resource(Session *s, unsigned long type, short id) { - Handle h; - int len, i; - char *t; - - h = GetResource(type, id); - if (h == NULL) - fatalbox("Can't get test resource"); - len = GetResourceSizeOnDisk(h); - DetachResource(h); - HNoPurge(h); - HLock(h); - t = *h; - from_backend(s->term, 0, t, len); - term_out(s->term); - DisposeHandle(h); + /* + * Select protocol. This is farmed out into a table in a + * separate file to enable an ssh-free variant. + */ + s->back = NULL; + for (i = 0; backends[i].backend != NULL; i++) + if (backends[i].protocol == s->cfg.protocol) { + s->back = backends[i].backend; + break; + } + if (s->back == NULL) { + fatalbox("Unsupported protocol number found"); + } + mac_startsession(s); + return; + + fail: + sfree(s); + return; } - -void mac_newsession(void) { - Session *s; - UInt32 starttime; - char msg[128]; - OSErr err; +void mac_startsession(Session *s) +{ + char *errmsg; - /* This should obviously be initialised by other means */ - s = smalloc(sizeof(*s)); - memset(s, 0, sizeof(*s)); - do_defaults(NULL, &s->cfg); - s->back = &loop_backend; - + init_ucs(s); /* XXX: Own storage management? */ if (HAVE_COLOR_QD()) s->window = GetNewCWindow(wTerminal, NULL, (WindowPtr)-1); @@ -152,44 +160,87 @@ void mac_newsession(void) { s->window = GetNewWindow(wTerminal, NULL, (WindowPtr)-1); SetWRefCon(s->window, (long)s); s->scrollbar = GetNewControl(cVScroll, s->window); - s->term = term_init(s); + s->term = term_init(&s->cfg, &s->ucsdata, s); + + mac_initfont(s); + mac_initpalette(s); + if (HAVE_COLOR_QD()) { + /* Set to FALSE to not get palette updates in the background. */ + SetPalette(s->window, s->palette, TRUE); + ActivatePalette(s->window); + } - s->logctx = log_init(s); + s->logctx = log_init(s, &s->cfg); term_provide_logctx(s->term, s->logctx); - s->back->init(s->term, &s->backhandle, "localhost", 23, &s->realhost, 0); + errmsg = s->back->init(s->term, &s->backhandle, &s->cfg, s->cfg.host, + s->cfg.port, &s->realhost, s->cfg.tcp_nodelay); + if (errmsg != NULL) + fatalbox("%s", errmsg); s->back->provide_logctx(s->backhandle, s->logctx); + set_title(s, s->realhost); term_provide_resize_fn(s->term, s->back->size, s->backhandle); mac_adjustsize(s, s->cfg.height, s->cfg.width); term_size(s->term, s->cfg.height, s->cfg.width, s->cfg.savelines); - s->ldisc = ldisc_create(s->term, s->back, s->backhandle, s); + s->ldisc = ldisc_create(&s->cfg, s->term, s->back, s->backhandle, s); ldisc_send(s->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */ - mac_initfont(s); - mac_initpalette(s); - s->attr_mask = ATTR_MASK; - if (HAVE_COLOR_QD()) { - /* Set to FALSE to not get palette updates in the background. */ - SetPalette(s->window, s->palette, TRUE); - ActivatePalette(s->window); - } ShowWindow(s->window); - starttime = TickCount(); - display_resource(s, 'pTST', 128); - sprintf(msg, "Elapsed ticks: %d\015\012", TickCount() - starttime); - inbuf_putstr(s, msg); - term_out(s->term); + s->next = sesslist; + s->prev = &sesslist; + if (s->next != NULL) + s->next->prev = &s->next; + sesslist = s; } +/* + * Try to work out a horizontal scaling factor for the current font + * that will give a chracter width of wantwidth. Return it in numer + * and denom (suitable for passing to StdText()). + */ +static void mac_workoutfontscale(Session *s, int wantwidth, + Point *numerp, Point *denomp) +{ + Point numer, denom, tmpnumer, tmpdenom; + int gotwidth, i; + const char text = 'W'; + FontInfo fi; + + numer.v = denom.v = 1; /* always */ + numer.h = denom.h = 1; + for (i = 0; i < 3; i++) { + tmpnumer = numer; + tmpdenom = denom; + if (s->window->grafProcs != NULL) + gotwidth = InvokeQDTxMeasUPP(1, &text, &tmpnumer, &tmpdenom, &fi, + s->window->grafProcs->txMeasProc); + else + gotwidth = StdTxMeas(1, &text, &tmpnumer, &tmpdenom, &fi); + /* The result of StdTxMeas must be scaled by the factors it returns. */ + gotwidth = FixRound(FixMul(gotwidth << 16, + FixRatio(tmpnumer.h, tmpdenom.h))); + if (gotwidth == wantwidth) + break; + numer.h *= wantwidth; + denom.h *= gotwidth; + } + *numerp = numer; + *denomp = denom; +} + +static UnicodeToTextFallbackUPP uni_to_font_fallback_upp; + static void mac_initfont(Session *s) { Str255 macfont; FontInfo fi; - + TextEncoding enc; + OptionBits fbflags; + SetPort(s->window); - macfont[0] = sprintf((char *)&macfont[1], "%s", s->cfg.font); + c2pstrcpy(macfont, s->cfg.font); GetFNum(macfont, &s->fontnum); TextFont(s->fontnum); TextFace(s->cfg.fontisbold ? bold : 0); @@ -199,14 +250,83 @@ static void mac_initfont(Session *s) { s->font_ascent = fi.ascent; s->font_leading = fi.leading; s->font_height = s->font_ascent + fi.descent + s->font_leading; + mac_workoutfontscale(s, s->font_width, + &s->font_stdnumer, &s->font_stddenom); + mac_workoutfontscale(s, s->font_width * 2, + &s->font_widenumer, &s->font_widedenom); + TextSize(s->cfg.fontheight * 2); + mac_workoutfontscale(s, s->font_width * 2, + &s->font_bignumer, &s->font_bigdenom); + TextSize(s->cfg.fontheight); if (!s->cfg.bold_colour) { TextFace(bold); s->font_boldadjust = s->font_width - CharWidth('W'); } else s->font_boldadjust = 0; + + if (s->uni_to_font != NULL) + DisposeUnicodeToTextInfo(&s->uni_to_font); + if (mac_gestalts.encvvers != 0 && + UpgradeScriptInfoToTextEncoding(kTextScriptDontCare, + kTextLanguageDontCare, + kTextRegionDontCare, macfont, + &enc) == noErr && + CreateUnicodeToTextInfoByEncoding(enc, &s->uni_to_font) == noErr) { + if (uni_to_font_fallback_upp == NULL) + uni_to_font_fallback_upp = + NewUnicodeToTextFallbackProc(&uni_to_font_fallback); + fbflags = kUnicodeFallbackCustomOnly; + if (mac_gestalts.uncvattr & kTECAddFallbackInterruptMask) + fbflags |= kUnicodeFallbackInterruptSafeMask; + if (SetFallbackUnicodeToText(s->uni_to_font, + uni_to_font_fallback_upp, fbflags, NULL) != noErr) { + DisposeUnicodeToTextInfo(&s->uni_to_font); + goto no_encv; + } + } else { + no_encv: + s->uni_to_font = NULL; + s->font_charset = + charset_from_macenc(FontToScript(s->fontnum), + GetScriptManagerVariable(smRegionCode), + mac_gestalts.sysvers, s->cfg.font); + } + mac_adjustsize(s, s->term->rows, s->term->cols); } +static pascal OSStatus uni_to_font_fallback(UniChar *ucp, + ByteCount ilen, ByteCount *iusedp, TextPtr obuf, ByteCount olen, + ByteCount *ousedp, LogicalAddress *cookie, ConstUnicodeMappingPtr mapping) +{ + + if (olen < 1) + return kTECOutputBufferFullStatus; + /* + * What I'd _like_ to do here is to somehow generate the + * missing-character glyph that every font is required to have. + * Unfortunately (and somewhat surprisingly), I can't find any way + * to actually ask for it explicitly. Bah. + */ + *obuf = '.'; + *iusedp = ilen; + *ousedp = 1; + return noErr; +} + +/* + * Called every time round the event loop. + */ +void mac_pollterm(void) +{ + Session *s; + + for (s = sesslist; s != NULL; s = s->next) { + term_out(s->term); + term_update(s->term); + } +} + /* * To be called whenever the window size changes. * rows and cols should be desired values. @@ -223,11 +343,13 @@ static void mac_adjustsize(Session *s, int newrows, int newcols) { MoveControl(s->scrollbar, winwidth - 15, -1); SizeControl(s->scrollbar, 16, winheight - 13); ShowControl(s->scrollbar); + mac_drawgrowicon(s); } static void mac_initpalette(Session *s) { - int i; + if (!HAVE_COLOR_QD()) + return; /* * Most colours should be inhibited on 2bpp displays. * Palette manager documentation suggests inhibiting all tolerant colours @@ -259,7 +381,7 @@ static void mac_adjustwinbg(Session *s) { if (!HAVE_COLOR_QD()) return; -#if TARGET_RT_CFM /* XXX doesn't link (at least for 68k) */ +#if !TARGET_CPU_68K if (mac_gestalts.windattr & gestaltWindowMgrPresent) SetWindowContentColor(s->window, &(*s->palette)->pmInfo[DEFAULT_BG].ciRGB); @@ -712,15 +834,53 @@ void request_paste(void *frontend) term_do_paste(s->term); } +static struct { + Rect msgrect; + Point msgorigin; + Point zeromouse; + Session *s; + char oldmsg[20]; +} growterm_state; + void mac_growterm(WindowPtr window, EventRecord *event) { Rect limits; long grow_result; int newrows, newcols; Session *s; + DragGrayRgnUPP draghooksave; + GrafPtr portsave; + FontInfo fi; s = (Session *)GetWRefCon(window); + + draghooksave = LMGetDragHook(); + growterm_state.oldmsg[0] = '\0'; + growterm_state.zeromouse = event->where; + growterm_state.zeromouse.h -= s->term->cols * s->font_width; + growterm_state.zeromouse.v -= s->term->rows * s->font_height; + growterm_state.s = s; + GetPort(&portsave); + SetPort(s->window); + BackColor(whiteColor); + ForeColor(blackColor); + TextFont(systemFont); + TextFace(0); + TextSize(12); + GetFontInfo(&fi); + SetRect(&growterm_state.msgrect, 0, 0, + StringWidth("\p99999x99999") + 4, fi.ascent + fi.descent + 4); + SetPt(&growterm_state.msgorigin, 2, fi.ascent + 2); + LMSetDragHook(NewDragGrayRgnUPP(mac_growtermdraghook)); + SetRect(&limits, s->font_width + 15, s->font_height, SHRT_MAX, SHRT_MAX); grow_result = GrowWindow(window, event->where, &limits); + + DisposeDragGrayRgnUPP(LMGetDragHook()); + LMSetDragHook(draghooksave); + InvalRect(&growterm_state.msgrect); + + SetPort(portsave); + if (grow_result != 0) { newrows = HiWord(grow_result) / s->font_height; newcols = (LoWord(grow_result) - 15) / s->font_width; @@ -729,6 +889,53 @@ void mac_growterm(WindowPtr window, EventRecord *event) { } } +static pascal void mac_growtermdraghook(void) +{ + Session *s = growterm_state.s; + GrafPtr portsave; + Point mouse; + char buf[20]; + unsigned char pbuf[20]; + int newrows, newcols; + + GetMouse(&mouse); + newrows = (mouse.v - growterm_state.zeromouse.v) / s->font_height; + if (newrows < 1) newrows = 1; + newcols = (mouse.h - growterm_state.zeromouse.h) / s->font_width; + if (newcols < 1) newcols = 1; + sprintf(buf, "%dx%d", newcols, newrows); + if (strcmp(buf, growterm_state.oldmsg) == 0) + return; + strcpy(growterm_state.oldmsg, buf); + c2pstrcpy(pbuf, buf); + + GetPort(&portsave); + SetPort(growterm_state.s->window); + EraseRect(&growterm_state.msgrect); + MoveTo(growterm_state.msgorigin.h, growterm_state.msgorigin.v); + DrawString(pbuf); + SetPort(portsave); +} + +void mac_closeterm(WindowPtr window) +{ + Session *s = (Session *)GetWRefCon(window); + + /* XXX warn on close */ + HideWindow(s->window); + *s->prev = s->next; + s->next->prev = s->prev; + ldisc_free(s->ldisc); + s->back->free(s->backhandle); + log_free(s->logctx); + if (s->uni_to_font != NULL) + DisposeUnicodeToTextInfo(&s->uni_to_font); + term_free(s->term); + DisposeWindow(s->window); + DisposePalette(s->palette); + sfree(s); +} + void mac_activateterm(WindowPtr window, Boolean active) { Session *s; @@ -777,25 +984,31 @@ void mac_updateterm(WindowPtr window) { static void mac_drawgrowicon(Session *s) { Rect clip; + RgnHandle savergn; SetPort(s->window); - /* Stop DrawGrowIcon giving us space for a horizontal scrollbar */ - SetRect(&clip, s->window->portRect.right - 15, SHRT_MIN, - SHRT_MAX, SHRT_MAX); + /* + * Stop DrawGrowIcon giving us space for a horizontal scrollbar + * See Tech Note TB575 for details. + */ + clip = s->window->portRect; + clip.left = clip.right - 15; + savergn = NewRgn(); + GetClip(savergn); ClipRect(&clip); DrawGrowIcon(s->window); - clip.left = SHRT_MIN; - ClipRect(&clip); + SetClip(savergn); + DisposeRgn(savergn); } struct do_text_args { Session *s; Rect textrect; - Rect leadrect; char *text; int len; unsigned long attr; int lattr; + Point numer, denom; }; /* @@ -808,29 +1021,74 @@ void do_text(Context ctx, int x, int y, char *text, int len, Session *s = ctx; int style = 0; struct do_text_args a; - RgnHandle textrgn; + RgnHandle textrgn, saveclip; + char mactextbuf[1024]; + UniChar unitextbuf[1024]; + wchar_t *unitextptr; + int i, fontwidth; + ByteCount iread, olen; + OSStatus err; + + assert(len <= 1024); SetPort(s->window); - + + fontwidth = s->font_width; + if ((lattr & LATTR_MODE) != LATTR_NORM) + fontwidth *= 2; + /* First check this text is relevant */ a.textrect.top = y * s->font_height; a.textrect.bottom = (y + 1) * s->font_height; - a.textrect.left = x * s->font_width; - a.textrect.right = (x + len) * s->font_width; + a.textrect.left = x * fontwidth; + a.textrect.right = (x + len) * fontwidth; + if (a.textrect.right > s->term->cols * s->font_width) + a.textrect.right = s->term->cols * s->font_width; if (!RectInRgn(&a.textrect, s->window->visRgn)) return; + /* Unpack Unicode from the mad format we get passed */ + for (i = 0; i < len; i++) + unitextbuf[i] = (unsigned char)text[i] | (attr & CSET_MASK); + + if (s->uni_to_font != NULL) { + err = ConvertFromUnicodeToText(s->uni_to_font, len * sizeof(UniChar), + unitextbuf, kUnicodeUseFallbacksMask, + 0, NULL, NULL, NULL, + 1024, &iread, &olen, mactextbuf); + if (err != noErr && err != kTECUsedFallbacksStatus) + olen = 0; + } else if (s->font_charset != CS_NONE) { + /* XXX this is bogus if wchar_t and UniChar are different sizes. */ + unitextptr = (wchar_t *)unitextbuf; + olen = charset_from_unicode(&unitextptr, &len, mactextbuf, 1024, + s->font_charset, NULL, ".", 1); + } else + olen = 0; + a.s = s; - a.text = text; - a.len = len; + a.text = mactextbuf; + a.len = olen; a.attr = attr; a.lattr = lattr; - if (s->font_leading > 0) - SetRect(&a.leadrect, - a.textrect.left, a.textrect.bottom - s->font_leading, - a.textrect.right, a.textrect.bottom); - else - SetRect(&a.leadrect, 0, 0, 0, 0); + switch (lattr & LATTR_MODE) { + case LATTR_NORM: + TextSize(s->cfg.fontheight); + a.numer = s->font_stdnumer; + a.denom = s->font_stddenom; + break; + case LATTR_WIDE: + TextSize(s->cfg.fontheight); + a.numer = s->font_widenumer; + a.denom = s->font_widedenom; + break; + case LATTR_TOP: + case LATTR_BOT: + TextSize(s->cfg.fontheight * 2); + a.numer = s->font_bignumer; + a.denom = s->font_bigdenom; + break; + } SetPort(s->window); TextFont(s->fontnum); if (s->cfg.fontisbold || (attr & ATTR_BOLD) && !s->cfg.bold_colour) @@ -838,8 +1096,7 @@ void do_text(Context ctx, int x, int y, char *text, int len, if (attr & ATTR_UNDER) style |= underline; TextFace(style); - TextSize(s->cfg.fontheight); - SetFractEnable(FALSE); /* We want characters on pixel boundaries */ + TextMode(srcOr); if (HAVE_COLOR_QD()) if (style & bold) { SpaceExtra(s->font_boldadjust << 16); @@ -848,12 +1105,17 @@ void do_text(Context ctx, int x, int y, char *text, int len, SpaceExtra(0); CharExtra(0); } + saveclip = NewRgn(); + GetClip(saveclip); + ClipRect(&a.textrect); textrgn = NewRgn(); RectRgn(textrgn, &a.textrect); if (HAVE_COLOR_QD()) DeviceLoop(textrgn, &do_text_for_device_upp, (long)&a, 0); else do_text_for_device(1, 0, NULL, (long)&a); + SetClip(saveclip); + DisposeRgn(saveclip); DisposeRgn(textrgn); /* Tell the window manager about it in case this isn't an update */ ValidRect(&a.textrect); @@ -862,58 +1124,72 @@ void do_text(Context ctx, int x, int y, char *text, int len, static pascal void do_text_for_device(short depth, short devflags, GDHandle device, long cookie) { struct do_text_args *a; - int bgcolour, fgcolour, bright; + int bgcolour, fgcolour, bright, reverse, tmp; a = (struct do_text_args *)cookie; bright = (a->attr & ATTR_BOLD) && a->s->cfg.bold_colour; + reverse = a->attr & ATTR_REVERSE; - TextMode(a->attr & ATTR_REVERSE ? notSrcCopy : srcCopy); + if (depth == 1 && (a->attr & TATTR_ACTCURS)) + reverse = !reverse; - switch (depth) { - case 1: - /* XXX This should be done with a _little_ more configurability */ - ForeColor(whiteColor); - BackColor(blackColor); - if (a->attr & TATTR_ACTCURS) - TextMode(a->attr & ATTR_REVERSE ? srcCopy : notSrcCopy); - break; - case 2: - if (a->attr & TATTR_ACTCURS) { - PmForeColor(CURSOR_FG); - PmBackColor(CURSOR_BG); - TextMode(srcCopy); + if (HAVE_COLOR_QD()) { + if (depth > 2) { + fgcolour = ((a->attr & ATTR_FGMASK) >> ATTR_FGSHIFT) * 2; + bgcolour = ((a->attr & ATTR_BGMASK) >> ATTR_BGSHIFT) * 2; } else { - PmForeColor(bright ? DEFAULT_FG_BOLD : DEFAULT_FG); - PmBackColor(DEFAULT_BG); + /* + * NB: bold reverse in 2bpp breaks with the usual PuTTY model and + * boldens the background, because that's all we can do. + */ + fgcolour = bright ? DEFAULT_FG_BOLD : DEFAULT_FG; + bgcolour = DEFAULT_BG; } - break; - default: - if (a->attr & TATTR_ACTCURS) { + if (reverse) { + tmp = fgcolour; + fgcolour = bgcolour; + bgcolour = tmp; + } + if (bright && depth > 2) + fgcolour++; + if ((a->attr & TATTR_ACTCURS) && depth > 1) { fgcolour = CURSOR_FG; bgcolour = CURSOR_BG; - TextMode(srcCopy); - } else { - fgcolour = ((a->attr & ATTR_FGMASK) >> ATTR_FGSHIFT) * 2; - bgcolour = ((a->attr & ATTR_BGMASK) >> ATTR_BGSHIFT) * 2; - if (bright) - if (a->attr & ATTR_REVERSE) - bgcolour++; - else - fgcolour++; } PmForeColor(fgcolour); PmBackColor(bgcolour); - break; + } else { /* No Color Quickdraw */ + /* XXX This should be done with a _little_ more configurability */ + if (reverse) { + ForeColor(blackColor); + BackColor(whiteColor); + } else { + ForeColor(whiteColor); + BackColor(blackColor); + } } - if (a->attr & ATTR_REVERSE) - PaintRect(&a->leadrect); - else - EraseRect(&a->leadrect); - MoveTo(a->textrect.left, a->textrect.top + a->s->font_ascent); + EraseRect(&a->textrect); + switch (a->lattr & LATTR_MODE) { + case LATTR_NORM: + case LATTR_WIDE: + MoveTo(a->textrect.left, a->textrect.top + a->s->font_ascent); + break; + case LATTR_TOP: + MoveTo(a->textrect.left, a->textrect.top + a->s->font_ascent * 2); + break; + case LATTR_BOT: + MoveTo(a->textrect.left, + a->textrect.top - a->s->font_height + a->s->font_ascent * 2); + break; + } /* FIXME: Sort out bold width adjustments on Original QuickDraw. */ - DrawText(a->text, 0, a->len); + if (a->s->window->grafProcs != NULL) + InvokeQDTextUPP(a->len, a->text, a->numer, a->denom, + a->s->window->grafProcs->textProc); + else + StdText(a->len, a->text, a->numer, a->denom); if (a->attr & TATTR_PASCURS) { PenNormal(); @@ -941,12 +1217,39 @@ void do_cursor(Context ctx, int x, int y, char *text, int len, * Should probably be called start_redraw or something. */ void pre_paint(Session *s) { + GDHandle gdh; + Rect myrect, tmprect; - s->attr_mask = ATTR_INVALID; - if (HAVE_COLOR_QD()) - DeviceLoop(s->window->visRgn, &mac_set_attr_mask_upp, (long)s, 0); - else - mac_set_attr_mask(1, 0, NULL, (long)s); + if (HAVE_COLOR_QD()) { + s->term->attr_mask = 0; + SetPort(s->window); + myrect = (*s->window->visRgn)->rgnBBox; + LocalToGlobal((Point *)&myrect.top); + LocalToGlobal((Point *)&myrect.bottom); + for (gdh = GetDeviceList(); + gdh != NULL; + gdh = GetNextDevice(gdh)) { + if (TestDeviceAttribute(gdh, screenDevice) && + TestDeviceAttribute(gdh, screenActive) && + SectRect(&(*gdh)->gdRect, &myrect, &tmprect)) { + switch ((*(*gdh)->gdPMap)->pixelSize) { + case 1: + if (s->cfg.bold_colour) + s->term->attr_mask |= ~(ATTR_COLOURS | + (s->cfg.bold_colour ? ATTR_BOLD : 0)); + break; + case 2: + s->term->attr_mask |= ~ATTR_COLOURS; + break; + default: + s->term->attr_mask = ~0; + return; /* No point checking more screens. */ + } + } + } + } else + s->term->attr_mask = ~(ATTR_COLOURS | + (s->cfg.bold_colour ? ATTR_BOLD : 0)); } Context get_ctx(void *frontend) { @@ -960,26 +1263,6 @@ void free_ctx(Context ctx) { } -static pascal void mac_set_attr_mask(short depth, short devflags, - GDHandle device, long cookie) { - - Session *s = (Session *)cookie; - - switch (depth) { - default: - s->attr_mask |= ATTR_FGMASK | ATTR_BGMASK; - /* FALLTHROUGH */ - case 2: - s->attr_mask |= ATTR_BOLD; - /* FALLTHROUGH */ - case 1: - s->attr_mask |= ATTR_UNDER | ATTR_REVERSE | TATTR_ACTCURS | - TATTR_PASCURS | ATTR_ASCII | ATTR_GBCHR | ATTR_LINEDRW | - (s->cfg.bold_colour ? 0 : ATTR_BOLD); - break; - } -} - /* * Presumably this does something in Windows */ @@ -1001,8 +1284,7 @@ void set_sbar(void *frontend, int total, int start, int page) { (*s->scrollbar)->contrlMin = 0; (*s->scrollbar)->contrlMax = total - page; SetControlValue(s->scrollbar, start); -#if TARGET_RT_CFM - /* XXX: This doesn't link for me. */ +#if !TARGET_CPU_68K if (mac_gestalts.cntlattr & gestaltControlMgrPresent) SetControlViewSize(s->scrollbar, page); #endif @@ -1055,7 +1337,7 @@ void set_title(void *frontend, char *title) { Session *s = frontend; Str255 mactitle; - mactitle[0] = sprintf((char *)&mactitle[1], "%s", title); + c2pstrcpy(mactitle, title); SetWTitle(s->window, mactitle); } @@ -1076,8 +1358,7 @@ void set_raw_mouse_mode(void *frontend, int activate) void request_resize(void *frontend, int w, int h) { Session *s = frontend; - s->term->cols = w; - s->term->rows = h; + term_size(s->term, h, w, s->cfg.savelines); mac_initfont(s); } @@ -1188,9 +1469,12 @@ void get_window_pixels(void *frontend, int *x, int *y) char *get_window_title(void *frontend, int icon) { Session *s = frontend; + Str255 ptitle; + static char title[256]; - /* Erm, we don't save this at the moment */ - return ""; + GetWTitle(s->window, ptitle); + p2cstrcpy(title, ptitle); + return title; } /* @@ -1267,26 +1551,52 @@ void palette_reset(void *frontend) { void do_scroll(void *frontend, int topline, int botline, int lines) { Session *s = frontend; Rect r; - RgnHandle update; + RgnHandle scrollrgn = NewRgn(); + RgnHandle movedupdate = NewRgn(); + RgnHandle update = NewRgn(); + Point g2l = { 0, 0 }; - /* FIXME: This is seriously broken on Original QuickDraw. No idea why. */ SetPort(s->window); + + /* + * Work out the part of the update region that will scrolled by + * this operation. + */ + if (lines > 0) + SetRectRgn(scrollrgn, 0, (topline + lines) * s->font_height, + s->term->cols * s->font_width, + (botline + 1) * s->font_height); + else + SetRectRgn(scrollrgn, 0, topline * s->font_height, + s->term->cols * s->font_width, + (botline - lines + 1) * s->font_height); + CopyRgn(((WindowPeek)s->window)->updateRgn, movedupdate); + GlobalToLocal(&g2l); + OffsetRgn(movedupdate, g2l.h, g2l.v); /* Convert to local co-ords. */ + SectRgn(scrollrgn, movedupdate, movedupdate); /* Clip scrolled section. */ + ValidRgn(movedupdate); + OffsetRgn(movedupdate, 0, -lines * s->font_height); /* Scroll it. */ + + PenNormal(); if (HAVE_COLOR_QD()) PmBackColor(DEFAULT_BG); else - BackColor(blackColor); - update = NewRgn(); + BackColor(blackColor); /* XXX make configurable */ SetRect(&r, 0, topline * s->font_height, s->term->cols * s->font_width, (botline + 1) * s->font_height); ScrollRect(&r, 0, - lines * s->font_height, update); - /* XXX: move update region? */ + InvalRgn(update); + InvalRgn(movedupdate); + + DisposeRgn(scrollrgn); + DisposeRgn(movedupdate); DisposeRgn(update); } void logevent(void *frontend, char *str) { - /* XXX Do something */ + fprintf(stderr, "%s\n", str); } /* Dummy routine, only required in plink. */