2004-11-27 13:20:21 +00:00
|
|
|
/* $Id$ */
|
2002-11-19 02:13:46 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 1999 Simon Tatham
|
|
|
|
* Copyright (c) 1999, 2002 Ben Harris
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person
|
|
|
|
* obtaining a copy of this software and associated documentation
|
|
|
|
* files (the "Software"), to deal in the Software without
|
|
|
|
* restriction, including without limitation the rights to use,
|
|
|
|
* copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
* sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following
|
|
|
|
* conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be
|
|
|
|
* included in all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
|
|
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
|
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
* SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* macterm.c -- Macintosh terminal front-end
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <MacTypes.h>
|
|
|
|
#include <Controls.h>
|
|
|
|
#include <ControlDefinitions.h>
|
2003-01-18 16:54:25 +00:00
|
|
|
#include <FixMath.h>
|
2002-11-19 02:13:46 +00:00
|
|
|
#include <Fonts.h>
|
|
|
|
#include <Gestalt.h>
|
2002-12-08 01:17:31 +00:00
|
|
|
#include <LowMem.h>
|
2002-11-19 02:13:46 +00:00
|
|
|
#include <MacMemory.h>
|
|
|
|
#include <MacWindows.h>
|
|
|
|
#include <MixedMode.h>
|
|
|
|
#include <Palettes.h>
|
|
|
|
#include <Quickdraw.h>
|
|
|
|
#include <QuickdrawText.h>
|
|
|
|
#include <Resources.h>
|
|
|
|
#include <Scrap.h>
|
|
|
|
#include <Script.h>
|
|
|
|
#include <Sound.h>
|
2002-12-13 00:02:48 +00:00
|
|
|
#include <TextCommon.h>
|
2002-11-19 02:13:46 +00:00
|
|
|
#include <ToolUtils.h>
|
2002-12-13 00:02:48 +00:00
|
|
|
#include <UnicodeConverter.h>
|
2002-11-19 02:13:46 +00:00
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "macresid.h"
|
|
|
|
#include "putty.h"
|
2002-12-31 22:49:03 +00:00
|
|
|
#include "charset.h"
|
2002-11-19 02:13:46 +00:00
|
|
|
#include "mac.h"
|
|
|
|
#include "terminal.h"
|
|
|
|
|
2005-01-21 00:02:59 +00:00
|
|
|
#define DEFAULT_FG 256
|
|
|
|
#define DEFAULT_FG_BOLD 257
|
|
|
|
#define DEFAULT_BG 258
|
|
|
|
#define DEFAULT_BG_BOLD 259
|
|
|
|
#define CURSOR_FG 260
|
|
|
|
#define CURSOR_BG 261
|
2002-11-19 02:13:46 +00:00
|
|
|
|
|
|
|
#define PTOCC(x) ((x) < 0 ? -(-(x - s->font_width - 1) / s->font_width) : \
|
|
|
|
(x) / s->font_width)
|
|
|
|
#define PTOCR(y) ((y) < 0 ? -(-(y - s->font_height - 1) / s->font_height) : \
|
|
|
|
(y) / s->font_height)
|
|
|
|
|
|
|
|
static void mac_initfont(Session *);
|
2002-12-13 00:02:48 +00:00
|
|
|
static pascal OSStatus uni_to_font_fallback(UniChar *, ByteCount, ByteCount *,
|
|
|
|
TextPtr, ByteCount, ByteCount *,
|
2003-02-04 01:53:50 +00:00
|
|
|
LogicalAddress,
|
2002-12-13 00:02:48 +00:00
|
|
|
ConstUnicodeMappingPtr);
|
2002-11-19 02:13:46 +00:00
|
|
|
static void mac_initpalette(Session *);
|
|
|
|
static void mac_adjustwinbg(Session *);
|
|
|
|
static void mac_adjustsize(Session *, int, int);
|
|
|
|
static void mac_drawgrowicon(Session *s);
|
2002-12-08 01:17:31 +00:00
|
|
|
static pascal void mac_growtermdraghook(void);
|
2002-11-19 02:13:46 +00:00
|
|
|
static pascal void mac_scrolltracker(ControlHandle, short);
|
|
|
|
static pascal void do_text_for_device(short, short, GDHandle, long);
|
|
|
|
static void text_click(Session *, EventRecord *);
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_activateterm(WindowPtr, EventRecord *);
|
|
|
|
static void mac_adjusttermcursor(WindowPtr, Point, RgnHandle);
|
|
|
|
static void mac_adjusttermmenus(WindowPtr);
|
|
|
|
static void mac_updateterm(WindowPtr);
|
|
|
|
static void mac_clickterm(WindowPtr, EventRecord *);
|
|
|
|
static void mac_growterm(WindowPtr, EventRecord *);
|
|
|
|
static void mac_keyterm(WindowPtr, EventRecord *);
|
|
|
|
static void mac_menuterm(WindowPtr, short, short);
|
|
|
|
static void mac_closeterm(WindowPtr);
|
2002-11-19 02:13:46 +00:00
|
|
|
|
|
|
|
void pre_paint(Session *s);
|
|
|
|
void post_paint(Session *s);
|
|
|
|
|
2002-12-30 18:21:17 +00:00
|
|
|
void mac_startsession(Session *s)
|
|
|
|
{
|
2003-05-04 14:18:18 +00:00
|
|
|
const char *errmsg;
|
2003-01-25 15:15:40 +00:00
|
|
|
int i;
|
2003-02-04 23:39:26 +00:00
|
|
|
WinInfo *wi;
|
2002-12-30 18:21:17 +00:00
|
|
|
|
2003-01-14 19:42:00 +00:00
|
|
|
init_ucs(s);
|
2003-01-25 15:15:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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");
|
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
/* XXX: Own storage management? */
|
|
|
|
if (HAVE_COLOR_QD())
|
|
|
|
s->window = GetNewCWindow(wTerminal, NULL, (WindowPtr)-1);
|
|
|
|
else
|
|
|
|
s->window = GetNewWindow(wTerminal, NULL, (WindowPtr)-1);
|
2003-03-29 23:07:55 +00:00
|
|
|
wi = snew(WinInfo);
|
2003-02-15 16:22:15 +00:00
|
|
|
memset(wi, 0, sizeof(*wi));
|
2003-02-04 23:39:26 +00:00
|
|
|
wi->s = s;
|
|
|
|
wi->wtype = wTerminal;
|
2003-02-15 16:22:15 +00:00
|
|
|
wi->activate = &mac_activateterm;
|
|
|
|
wi->adjustcursor = &mac_adjusttermcursor;
|
|
|
|
wi->adjustmenus = &mac_adjusttermmenus;
|
|
|
|
wi->update = &mac_updateterm;
|
|
|
|
wi->click = &mac_clickterm;
|
|
|
|
wi->grow = &mac_growterm;
|
|
|
|
wi->key = &mac_keyterm;
|
|
|
|
wi->menu = &mac_menuterm;
|
|
|
|
wi->close = &mac_closeterm;
|
2003-02-04 23:39:26 +00:00
|
|
|
SetWRefCon(s->window, (long)wi);
|
2002-11-19 02:13:46 +00:00
|
|
|
s->scrollbar = GetNewControl(cVScroll, s->window);
|
2003-01-14 19:42:00 +00:00
|
|
|
s->term = term_init(&s->cfg, &s->ucsdata, s);
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-01-05 10:52:56 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2003-02-07 01:38:12 +00:00
|
|
|
s->logctx = log_init(s->term, &s->cfg);
|
2002-11-19 02:13:46 +00:00
|
|
|
term_provide_logctx(s->term, s->logctx);
|
|
|
|
|
2003-04-12 21:06:34 +00:00
|
|
|
errmsg = s->back->init(s, &s->backhandle, &s->cfg, s->cfg.host,
|
2004-06-20 17:07:38 +00:00
|
|
|
s->cfg.port, &s->realhost, s->cfg.tcp_nodelay,
|
|
|
|
s->cfg.tcp_keepalives);
|
2003-01-12 14:44:12 +00:00
|
|
|
if (errmsg != NULL)
|
|
|
|
fatalbox("%s", errmsg);
|
2002-11-19 02:13:46 +00:00
|
|
|
s->back->provide_logctx(s->backhandle, s->logctx);
|
2003-01-12 16:25:58 +00:00
|
|
|
set_title(s, s->realhost);
|
2002-11-19 02:13:46 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2002-11-23 20:02:38 +00:00
|
|
|
s->ldisc = ldisc_create(&s->cfg, s->term, s->back, s->backhandle, s);
|
2002-11-19 02:13:46 +00:00
|
|
|
ldisc_send(s->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */
|
|
|
|
|
|
|
|
ShowWindow(s->window);
|
2003-01-08 22:46:12 +00:00
|
|
|
s->next = sesslist;
|
2003-01-15 23:30:21 +00:00
|
|
|
s->prev = &sesslist;
|
2003-01-12 14:23:00 +00:00
|
|
|
if (s->next != NULL)
|
2003-01-12 13:50:04 +00:00
|
|
|
s->next->prev = &s->next;
|
2003-01-08 22:46:12 +00:00
|
|
|
sesslist = s;
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
2003-01-14 18:43:26 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
2003-04-12 21:07:25 +00:00
|
|
|
CQDProcsPtr gp = GetPortGrafProcs(GetWindowPort(s->window));
|
2003-02-04 01:53:50 +00:00
|
|
|
#else
|
2003-04-12 21:07:25 +00:00
|
|
|
QDProcsPtr gp = s->window->grafProcs;
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2003-01-14 18:43:26 +00:00
|
|
|
|
|
|
|
numer.v = denom.v = 1; /* always */
|
|
|
|
numer.h = denom.h = 1;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
tmpnumer = numer;
|
|
|
|
tmpdenom = denom;
|
2003-02-04 01:53:50 +00:00
|
|
|
if (gp != NULL)
|
2003-01-14 18:43:26 +00:00
|
|
|
gotwidth = InvokeQDTxMeasUPP(1, &text, &tmpnumer, &tmpdenom, &fi,
|
2003-02-04 01:53:50 +00:00
|
|
|
gp->txMeasProc);
|
2003-01-14 18:43:26 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2002-12-13 00:02:48 +00:00
|
|
|
static UnicodeToTextFallbackUPP uni_to_font_fallback_upp;
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_initfont(Session *s)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
FontInfo fi;
|
2002-12-13 00:02:48 +00:00
|
|
|
TextEncoding enc;
|
2003-01-02 00:33:40 +00:00
|
|
|
OptionBits fbflags;
|
2002-12-13 00:02:48 +00:00
|
|
|
|
2003-02-04 02:03:53 +00:00
|
|
|
SetPort((GrafPtr)GetWindowPort(s->window));
|
2003-02-01 15:44:08 +00:00
|
|
|
GetFNum(s->cfg.font.name, &s->fontnum);
|
2002-11-19 02:13:46 +00:00
|
|
|
TextFont(s->fontnum);
|
2003-02-01 15:44:08 +00:00
|
|
|
TextFace(s->cfg.font.face);
|
|
|
|
TextSize(s->cfg.font.size);
|
2002-11-19 02:13:46 +00:00
|
|
|
GetFontInfo(&fi);
|
|
|
|
s->font_width = CharWidth('W'); /* Well, it's what NCSA uses. */
|
|
|
|
s->font_ascent = fi.ascent;
|
|
|
|
s->font_leading = fi.leading;
|
|
|
|
s->font_height = s->font_ascent + fi.descent + s->font_leading;
|
2003-01-14 18:43:26 +00:00
|
|
|
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);
|
2003-02-01 15:44:08 +00:00
|
|
|
TextSize(s->cfg.font.size * 2);
|
2003-01-14 18:43:26 +00:00
|
|
|
mac_workoutfontscale(s, s->font_width * 2,
|
|
|
|
&s->font_bignumer, &s->font_bigdenom);
|
2003-02-01 15:44:08 +00:00
|
|
|
TextSize(s->cfg.font.size);
|
2002-11-19 02:13:46 +00:00
|
|
|
if (!s->cfg.bold_colour) {
|
|
|
|
TextFace(bold);
|
|
|
|
s->font_boldadjust = s->font_width - CharWidth('W');
|
|
|
|
} else
|
|
|
|
s->font_boldadjust = 0;
|
2002-12-13 00:02:48 +00:00
|
|
|
|
|
|
|
if (s->uni_to_font != NULL)
|
|
|
|
DisposeUnicodeToTextInfo(&s->uni_to_font);
|
2003-01-01 19:51:13 +00:00
|
|
|
if (mac_gestalts.encvvers != 0 &&
|
2002-12-13 00:02:48 +00:00
|
|
|
UpgradeScriptInfoToTextEncoding(kTextScriptDontCare,
|
|
|
|
kTextLanguageDontCare,
|
2003-02-01 15:44:08 +00:00
|
|
|
kTextRegionDontCare, s->cfg.font.name,
|
2003-01-01 19:51:13 +00:00
|
|
|
&enc) == noErr &&
|
|
|
|
CreateUnicodeToTextInfoByEncoding(enc, &s->uni_to_font) == noErr) {
|
2002-12-13 00:02:48 +00:00
|
|
|
if (uni_to_font_fallback_upp == NULL)
|
|
|
|
uni_to_font_fallback_upp =
|
2003-02-04 01:53:50 +00:00
|
|
|
NewUnicodeToTextFallbackUPP(&uni_to_font_fallback);
|
2003-01-02 00:33:40 +00:00
|
|
|
fbflags = kUnicodeFallbackCustomOnly;
|
|
|
|
if (mac_gestalts.uncvattr & kTECAddFallbackInterruptMask)
|
|
|
|
fbflags |= kUnicodeFallbackInterruptSafeMask;
|
2002-12-13 00:02:48 +00:00
|
|
|
if (SetFallbackUnicodeToText(s->uni_to_font,
|
2003-01-02 00:33:40 +00:00
|
|
|
uni_to_font_fallback_upp, fbflags, NULL) != noErr) {
|
2002-12-13 00:02:48 +00:00
|
|
|
DisposeUnicodeToTextInfo(&s->uni_to_font);
|
2003-01-02 00:33:40 +00:00
|
|
|
goto no_encv;
|
2002-12-13 00:02:48 +00:00
|
|
|
}
|
2003-01-01 19:51:13 +00:00
|
|
|
} else {
|
2003-02-01 15:44:08 +00:00
|
|
|
char cfontname[256];
|
|
|
|
|
2003-01-02 00:33:40 +00:00
|
|
|
no_encv:
|
2003-01-01 19:51:13 +00:00
|
|
|
s->uni_to_font = NULL;
|
2003-02-01 15:44:08 +00:00
|
|
|
p2cstrcpy(cfontname, s->cfg.font.name);
|
2003-01-01 19:51:13 +00:00
|
|
|
s->font_charset =
|
|
|
|
charset_from_macenc(FontToScript(s->fontnum),
|
|
|
|
GetScriptManagerVariable(smRegionCode),
|
2003-02-01 15:44:08 +00:00
|
|
|
mac_gestalts.sysvers, cfontname);
|
2002-12-13 00:02:48 +00:00
|
|
|
}
|
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
mac_adjustsize(s, s->term->rows, s->term->cols);
|
|
|
|
}
|
|
|
|
|
2002-12-13 00:02:48 +00:00
|
|
|
static pascal OSStatus uni_to_font_fallback(UniChar *ucp,
|
|
|
|
ByteCount ilen, ByteCount *iusedp, TextPtr obuf, ByteCount olen,
|
2003-02-04 01:53:50 +00:00
|
|
|
ByteCount *ousedp, LogicalAddress cookie, ConstUnicodeMappingPtr mapping)
|
2002-12-13 00:02:48 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
if (olen < 1)
|
|
|
|
return kTECOutputBufferFullStatus;
|
2002-12-31 20:11:38 +00:00
|
|
|
/*
|
|
|
|
* 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 = '.';
|
2002-12-13 00:02:48 +00:00
|
|
|
*iusedp = ilen;
|
|
|
|
*ousedp = 1;
|
|
|
|
return noErr;
|
|
|
|
}
|
|
|
|
|
2003-01-08 22:46:12 +00:00
|
|
|
/*
|
|
|
|
* Called every time round the event loop.
|
|
|
|
*/
|
|
|
|
void mac_pollterm(void)
|
|
|
|
{
|
|
|
|
Session *s;
|
|
|
|
|
|
|
|
for (s = sesslist; s != NULL; s = s->next) {
|
|
|
|
term_update(s->term);
|
|
|
|
}
|
|
|
|
}
|
2002-12-13 00:02:48 +00:00
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
/*
|
|
|
|
* To be called whenever the window size changes.
|
|
|
|
* rows and cols should be desired values.
|
|
|
|
* It's assumed the terminal emulator will be informed, and will set rows
|
|
|
|
* and cols for us.
|
|
|
|
*/
|
|
|
|
static void mac_adjustsize(Session *s, int newrows, int newcols) {
|
|
|
|
int winwidth, winheight;
|
|
|
|
|
|
|
|
winwidth = newcols * s->font_width + 15;
|
|
|
|
winheight = newrows * s->font_height;
|
|
|
|
SizeWindow(s->window, winwidth, winheight, true);
|
|
|
|
HideControl(s->scrollbar);
|
|
|
|
MoveControl(s->scrollbar, winwidth - 15, -1);
|
|
|
|
SizeControl(s->scrollbar, 16, winheight - 13);
|
|
|
|
ShowControl(s->scrollbar);
|
2002-12-09 23:26:52 +00:00
|
|
|
mac_drawgrowicon(s);
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_initpalette(Session *s)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2002-11-23 22:36:56 +00:00
|
|
|
if (!HAVE_COLOR_QD())
|
|
|
|
return;
|
2002-11-19 02:13:46 +00:00
|
|
|
/*
|
|
|
|
* Most colours should be inhibited on 2bpp displays.
|
|
|
|
* Palette manager documentation suggests inhibiting all tolerant colours
|
|
|
|
* on greyscale displays.
|
|
|
|
*/
|
2002-11-20 00:33:44 +00:00
|
|
|
#define PM_NORMAL ( pmTolerant | pmInhibitC2 | \
|
|
|
|
pmInhibitG2 | pmInhibitG4 | pmInhibitG8 )
|
2002-11-19 02:13:46 +00:00
|
|
|
#define PM_TOLERANCE 0x2000
|
2005-01-21 00:02:59 +00:00
|
|
|
s->palette = NewPalette(262, NULL, PM_NORMAL, PM_TOLERANCE);
|
2002-11-19 02:13:46 +00:00
|
|
|
if (s->palette == NULL)
|
|
|
|
fatalbox("Unable to create palette");
|
|
|
|
/* In 2bpp, these are the colours we want most. */
|
|
|
|
SetEntryUsage(s->palette, DEFAULT_BG,
|
|
|
|
PM_NORMAL &~ pmInhibitC2, PM_TOLERANCE);
|
|
|
|
SetEntryUsage(s->palette, DEFAULT_FG,
|
|
|
|
PM_NORMAL &~ pmInhibitC2, PM_TOLERANCE);
|
|
|
|
SetEntryUsage(s->palette, DEFAULT_FG_BOLD,
|
|
|
|
PM_NORMAL &~ pmInhibitC2, PM_TOLERANCE);
|
2002-11-20 00:33:44 +00:00
|
|
|
SetEntryUsage(s->palette, CURSOR_BG,
|
2002-11-19 02:13:46 +00:00
|
|
|
PM_NORMAL &~ pmInhibitC2, PM_TOLERANCE);
|
|
|
|
palette_reset(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the background colour of the window correctly. Should be
|
|
|
|
* called whenever the default background changes.
|
|
|
|
*/
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_adjustwinbg(Session *s)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
|
|
|
|
if (!HAVE_COLOR_QD())
|
|
|
|
return;
|
2003-01-04 00:13:18 +00:00
|
|
|
#if !TARGET_CPU_68K
|
2002-11-19 02:13:46 +00:00
|
|
|
if (mac_gestalts.windattr & gestaltWindowMgrPresent)
|
|
|
|
SetWindowContentColor(s->window,
|
|
|
|
&(*s->palette)->pmInfo[DEFAULT_BG].ciRGB);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
2003-02-04 01:53:50 +00:00
|
|
|
#if !TARGET_API_MAC_CARBON
|
2002-11-19 02:13:46 +00:00
|
|
|
if (s->wctab == NULL)
|
|
|
|
s->wctab = (WCTabHandle)NewHandle(sizeof(**s->wctab));
|
|
|
|
if (s->wctab == NULL)
|
|
|
|
return; /* do without */
|
|
|
|
(*s->wctab)->wCSeed = 0;
|
|
|
|
(*s->wctab)->wCReserved = 0;
|
|
|
|
(*s->wctab)->ctSize = 0;
|
|
|
|
(*s->wctab)->ctTable[0].value = wContentColor;
|
|
|
|
(*s->wctab)->ctTable[0].rgb = (*s->palette)->pmInfo[DEFAULT_BG].ciRGB;
|
|
|
|
SetWinColor(s->window, s->wctab);
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the cursor shape correctly
|
|
|
|
*/
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_adjusttermcursor(WindowPtr window, Point mouse,
|
|
|
|
RgnHandle cursrgn)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s;
|
|
|
|
ControlHandle control;
|
|
|
|
short part;
|
|
|
|
int x, y;
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
Cursor arrow;
|
|
|
|
Rect rect;
|
|
|
|
RgnHandle visrgn;
|
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-02-04 02:03:53 +00:00
|
|
|
SetPort((GrafPtr)GetWindowPort(window));
|
2003-02-04 23:39:26 +00:00
|
|
|
s = mac_windowsession(window);
|
2002-11-19 02:13:46 +00:00
|
|
|
GlobalToLocal(&mouse);
|
|
|
|
part = FindControl(mouse, window, &control);
|
|
|
|
if (control == s->scrollbar) {
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
SetCursor(GetQDGlobalsArrow(&arrow));
|
|
|
|
RectRgn(cursrgn, GetControlBounds(s->scrollbar, &rect));
|
|
|
|
#else
|
2002-11-19 02:13:46 +00:00
|
|
|
SetCursor(&qd.arrow);
|
|
|
|
RectRgn(cursrgn, &(*s->scrollbar)->contrlRect);
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
} else {
|
|
|
|
x = mouse.h / s->font_width;
|
|
|
|
y = mouse.v / s->font_height;
|
2003-02-04 01:53:50 +00:00
|
|
|
if (s->raw_mouse) {
|
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
SetCursor(GetQDGlobalsArrow(&arrow));
|
|
|
|
#else
|
2002-11-19 02:13:46 +00:00
|
|
|
SetCursor(&qd.arrow);
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
|
|
|
} else
|
2002-11-19 02:13:46 +00:00
|
|
|
SetCursor(*GetCursor(iBeamCursor));
|
|
|
|
/* Ask for shape changes if we leave this character cell. */
|
|
|
|
SetRectRgn(cursrgn, x * s->font_width, y * s->font_height,
|
|
|
|
(x + 1) * s->font_width, (y + 1) * s->font_height);
|
|
|
|
}
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
visrgn = NewRgn();
|
|
|
|
GetPortVisibleRegion(GetWindowPort(window), visrgn);
|
|
|
|
SectRgn(cursrgn, visrgn, cursrgn);
|
|
|
|
DisposeRgn(visrgn);
|
|
|
|
#else
|
|
|
|
SectRgn(cursrgn, window->visRgn, cursrgn);
|
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Enable/disable menu items based on the active terminal window.
|
|
|
|
*/
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
#define DisableItem DisableMenuItem
|
|
|
|
#define EnableItem EnableMenuItem
|
|
|
|
#endif
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_adjusttermmenus(WindowPtr window)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s;
|
|
|
|
MenuHandle menu;
|
2003-02-04 01:53:50 +00:00
|
|
|
#if !TARGET_API_MAC_CARBON
|
2002-11-19 02:13:46 +00:00
|
|
|
long offset;
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-02-04 23:39:26 +00:00
|
|
|
s = mac_windowsession(window);
|
2003-01-18 20:09:21 +00:00
|
|
|
menu = GetMenuHandle(mFile);
|
|
|
|
DisableItem(menu, iSave); /* XXX enable if modified */
|
|
|
|
EnableItem(menu, iSaveAs);
|
2005-01-26 23:30:34 +00:00
|
|
|
EnableItem(menu, iChange);
|
2003-01-25 15:15:40 +00:00
|
|
|
EnableItem(menu, iDuplicate);
|
2002-11-19 02:13:46 +00:00
|
|
|
menu = GetMenuHandle(mEdit);
|
|
|
|
EnableItem(menu, 0);
|
|
|
|
DisableItem(menu, iUndo);
|
|
|
|
DisableItem(menu, iCut);
|
|
|
|
if (1/*s->term->selstate == SELECTED*/)
|
|
|
|
EnableItem(menu, iCopy);
|
|
|
|
else
|
|
|
|
DisableItem(menu, iCopy);
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
if (1)
|
|
|
|
#else
|
2003-02-04 02:08:03 +00:00
|
|
|
if (GetScrap(NULL, kScrapFlavorTypeText, &offset) == noTypeErr)
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
DisableItem(menu, iPaste);
|
|
|
|
else
|
|
|
|
EnableItem(menu, iPaste);
|
|
|
|
DisableItem(menu, iClear);
|
|
|
|
EnableItem(menu, iSelectAll);
|
2003-02-07 01:38:12 +00:00
|
|
|
menu = GetMenuHandle(mWindow);
|
|
|
|
EnableItem(menu, 0);
|
|
|
|
EnableItem(menu, iShowEventLog);
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_menuterm(WindowPtr window, short menu, short item)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s;
|
|
|
|
|
2003-02-04 23:39:26 +00:00
|
|
|
s = mac_windowsession(window);
|
2002-11-19 02:13:46 +00:00
|
|
|
switch (menu) {
|
|
|
|
case mEdit:
|
|
|
|
switch (item) {
|
|
|
|
case iCopy:
|
|
|
|
/* term_copy(s); */
|
|
|
|
break;
|
|
|
|
case iPaste:
|
|
|
|
term_do_paste(s->term);
|
|
|
|
break;
|
|
|
|
}
|
2003-02-07 01:38:12 +00:00
|
|
|
break;
|
|
|
|
case mWindow:
|
|
|
|
switch(item) {
|
|
|
|
case iShowEventLog:
|
|
|
|
mac_showeventlog(s);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_clickterm(WindowPtr window, EventRecord *event)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s;
|
|
|
|
Point mouse;
|
|
|
|
ControlHandle control;
|
|
|
|
int part;
|
2003-02-04 01:53:50 +00:00
|
|
|
static ControlActionUPP mac_scrolltracker_upp = NULL;
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-02-04 23:39:26 +00:00
|
|
|
s = mac_windowsession(window);
|
2003-02-04 02:03:53 +00:00
|
|
|
SetPort((GrafPtr)GetWindowPort(window));
|
2002-11-19 02:13:46 +00:00
|
|
|
mouse = event->where;
|
|
|
|
GlobalToLocal(&mouse);
|
|
|
|
part = FindControl(mouse, window, &control);
|
|
|
|
if (control == s->scrollbar) {
|
|
|
|
switch (part) {
|
|
|
|
case kControlIndicatorPart:
|
|
|
|
if (TrackControl(control, mouse, NULL) == kControlIndicatorPart)
|
|
|
|
term_scroll(s->term, +1, GetControlValue(control));
|
|
|
|
break;
|
|
|
|
case kControlUpButtonPart:
|
|
|
|
case kControlDownButtonPart:
|
|
|
|
case kControlPageUpPart:
|
|
|
|
case kControlPageDownPart:
|
2003-02-04 01:53:50 +00:00
|
|
|
if (mac_scrolltracker_upp == NULL)
|
|
|
|
mac_scrolltracker_upp =
|
|
|
|
NewControlActionUPP(&mac_scrolltracker);
|
|
|
|
TrackControl(control, mouse, mac_scrolltracker_upp);
|
2002-11-19 02:13:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
text_click(s, event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
static void text_click(Session *s, EventRecord *event)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Point localwhere;
|
|
|
|
int row, col;
|
|
|
|
static UInt32 lastwhen = 0;
|
|
|
|
static Session *lastsess = NULL;
|
|
|
|
static int lastrow = -1, lastcol = -1;
|
|
|
|
static Mouse_Action lastact = MA_NOTHING;
|
|
|
|
|
2003-02-04 02:03:53 +00:00
|
|
|
SetPort((GrafPtr)GetWindowPort(s->window));
|
2002-11-19 02:13:46 +00:00
|
|
|
localwhere = event->where;
|
|
|
|
GlobalToLocal(&localwhere);
|
|
|
|
|
|
|
|
col = PTOCC(localwhere.h);
|
|
|
|
row = PTOCR(localwhere.v);
|
|
|
|
if (event->when - lastwhen < GetDblTime() &&
|
|
|
|
row == lastrow && col == lastcol && s == lastsess)
|
|
|
|
lastact = (lastact == MA_CLICK ? MA_2CLK :
|
|
|
|
lastact == MA_2CLK ? MA_3CLK :
|
|
|
|
lastact == MA_3CLK ? MA_CLICK : MA_NOTHING);
|
|
|
|
else
|
|
|
|
lastact = MA_CLICK;
|
2003-01-25 16:16:45 +00:00
|
|
|
term_mouse(s->term, MBT_LEFT,
|
|
|
|
event->modifiers & shiftKey ? MBT_EXTEND : MBT_SELECT,
|
2002-11-19 02:13:46 +00:00
|
|
|
lastact, col, row, event->modifiers & shiftKey,
|
|
|
|
event->modifiers & controlKey, event->modifiers & optionKey);
|
|
|
|
lastsess = s;
|
|
|
|
lastrow = row;
|
|
|
|
lastcol = col;
|
|
|
|
while (StillDown()) {
|
|
|
|
GetMouse(&localwhere);
|
|
|
|
col = PTOCC(localwhere.h);
|
|
|
|
row = PTOCR(localwhere.v);
|
2003-01-25 16:16:45 +00:00
|
|
|
term_mouse(s->term, MBT_LEFT,
|
|
|
|
event->modifiers & shiftKey ? MBT_EXTEND : MBT_SELECT,
|
2002-11-19 02:13:46 +00:00
|
|
|
MA_DRAG, col, row, event->modifiers & shiftKey,
|
|
|
|
event->modifiers & controlKey,
|
|
|
|
event->modifiers & optionKey);
|
|
|
|
if (row > s->term->rows - 1)
|
|
|
|
term_scroll(s->term, 0, row - (s->term->rows - 1));
|
|
|
|
else if (row < 0)
|
|
|
|
term_scroll(s->term, 0, row);
|
|
|
|
}
|
2003-01-25 16:16:45 +00:00
|
|
|
term_mouse(s->term, MBT_LEFT,
|
|
|
|
event->modifiers & shiftKey ? MBT_EXTEND : MBT_SELECT,
|
2002-11-19 02:13:46 +00:00
|
|
|
MA_RELEASE, col, row, event->modifiers & shiftKey,
|
|
|
|
event->modifiers & controlKey, event->modifiers & optionKey);
|
|
|
|
lastwhen = TickCount();
|
|
|
|
}
|
|
|
|
|
2003-01-25 17:20:54 +00:00
|
|
|
void write_clip(void *cookie, wchar_t *data, int len, int must_deselect)
|
|
|
|
{
|
2003-02-04 01:53:50 +00:00
|
|
|
#if !TARGET_API_MAC_CARBON
|
2003-01-25 17:20:54 +00:00
|
|
|
Session *s = cookie;
|
|
|
|
char *mactextbuf;
|
|
|
|
ByteCount iread, olen;
|
|
|
|
wchar_t *unitextptr;
|
|
|
|
StScrpRec *stsc;
|
|
|
|
size_t stsz;
|
|
|
|
OSErr err;
|
|
|
|
int i;
|
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
/*
|
|
|
|
* See "Programming with the Text Encoding Conversion Manager"
|
|
|
|
* Appendix E for Unicode scrap conventions.
|
|
|
|
*
|
|
|
|
* XXX Maybe PICT scrap too.
|
|
|
|
*/
|
|
|
|
if (ZeroScrap() != noErr)
|
|
|
|
return;
|
2003-02-04 02:08:03 +00:00
|
|
|
PutScrap(len * sizeof(*data), kScrapFlavorTypeUnicode, data);
|
2003-01-25 17:20:54 +00:00
|
|
|
|
|
|
|
/* Replace LINE SEPARATORs with CR for TEXT output. */
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
if (data[i] == 0x2028)
|
|
|
|
data[i] = 0x000d;
|
|
|
|
|
2003-03-29 23:07:55 +00:00
|
|
|
mactextbuf = snewn(len, char); /* XXX DBCS */
|
2003-01-25 17:20:54 +00:00
|
|
|
if (s->uni_to_font != NULL) {
|
|
|
|
err = ConvertFromUnicodeToText(s->uni_to_font, len * sizeof(UniChar),
|
|
|
|
(UniChar *)data,
|
|
|
|
kUnicodeUseFallbacksMask,
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
len, &iread, &olen, mactextbuf);
|
|
|
|
if (err != noErr && err != kTECUsedFallbacksStatus)
|
|
|
|
return;
|
|
|
|
} else if (s->font_charset != CS_NONE) {
|
|
|
|
unitextptr = data;
|
|
|
|
olen = charset_from_unicode(&unitextptr, &len, mactextbuf, 1024,
|
|
|
|
s->font_charset, NULL, ".", 1);
|
|
|
|
} else
|
|
|
|
return;
|
2003-02-04 02:08:03 +00:00
|
|
|
PutScrap(olen, kScrapFlavorTypeText, mactextbuf);
|
2003-01-25 17:20:54 +00:00
|
|
|
sfree(mactextbuf);
|
|
|
|
|
|
|
|
stsz = offsetof(StScrpRec, scrpStyleTab) + sizeof(ScrpSTElement);
|
|
|
|
stsc = smalloc(stsz);
|
|
|
|
stsc->scrpNStyles = 1;
|
|
|
|
stsc->scrpStyleTab[0].scrpStartChar = 0;
|
|
|
|
stsc->scrpStyleTab[0].scrpHeight = s->font_height;
|
|
|
|
stsc->scrpStyleTab[0].scrpAscent = s->font_ascent;
|
|
|
|
stsc->scrpStyleTab[0].scrpFont = s->fontnum;
|
|
|
|
stsc->scrpStyleTab[0].scrpFace = 0;
|
2003-02-01 15:44:08 +00:00
|
|
|
stsc->scrpStyleTab[0].scrpSize = s->cfg.font.size;
|
2003-01-25 17:20:54 +00:00
|
|
|
stsc->scrpStyleTab[0].scrpColor.red = 0;
|
|
|
|
stsc->scrpStyleTab[0].scrpColor.green = 0;
|
|
|
|
stsc->scrpStyleTab[0].scrpColor.blue = 0;
|
2003-02-04 02:08:03 +00:00
|
|
|
PutScrap(stsz, kScrapFlavorTypeTextStyle, stsc);
|
2003-01-25 17:20:54 +00:00
|
|
|
sfree(stsc);
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
void get_clip(void *frontend, wchar_t **p, int *lenp)
|
|
|
|
{
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
*lenp = 0;
|
|
|
|
#else
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s = frontend;
|
|
|
|
static Handle h = NULL;
|
2003-01-25 19:23:03 +00:00
|
|
|
static wchar_t *data = NULL;
|
|
|
|
Handle texth;
|
2002-11-19 02:13:46 +00:00
|
|
|
long offset;
|
2003-01-25 19:23:03 +00:00
|
|
|
int textlen;
|
|
|
|
TextEncoding enc;
|
|
|
|
TextToUnicodeInfo scrap_to_uni;
|
|
|
|
ByteCount iread, olen;
|
|
|
|
int charset;
|
|
|
|
char *tptr;
|
|
|
|
OSErr err;
|
2002-11-19 02:13:46 +00:00
|
|
|
|
|
|
|
if (p == NULL) {
|
|
|
|
/* release memory */
|
|
|
|
if (h != NULL)
|
|
|
|
DisposeHandle(h);
|
|
|
|
h = NULL;
|
2003-01-25 19:23:03 +00:00
|
|
|
if (data != NULL)
|
|
|
|
sfree(data);
|
|
|
|
data = NULL;
|
|
|
|
} else {
|
2003-02-04 02:08:03 +00:00
|
|
|
if (GetScrap(NULL, kScrapFlavorTypeUnicode, &offset) > 0) {
|
2003-01-25 19:23:03 +00:00
|
|
|
if (h == NULL)
|
|
|
|
h = NewHandle(0);
|
2003-02-04 02:08:03 +00:00
|
|
|
*lenp =
|
|
|
|
GetScrap(h, kScrapFlavorTypeUnicode, &offset) / sizeof(**p);
|
2002-11-19 02:13:46 +00:00
|
|
|
HLock(h);
|
|
|
|
*p = (wchar_t *)*h;
|
2003-02-04 02:08:03 +00:00
|
|
|
} else if (GetScrap(NULL, kScrapFlavorTypeText, &offset) > 0) {
|
2003-01-25 19:23:03 +00:00
|
|
|
texth = NewHandle(0);
|
2003-02-04 02:08:03 +00:00
|
|
|
textlen = GetScrap(texth, kScrapFlavorTypeText, &offset);
|
2003-01-25 19:23:03 +00:00
|
|
|
HLock(texth);
|
2003-03-29 23:07:55 +00:00
|
|
|
data = snewn(textlen, wchar_t);
|
2003-01-25 19:23:03 +00:00
|
|
|
/* XXX should use 'styl' scrap if it's there. */
|
|
|
|
if (mac_gestalts.encvvers != 0 &&
|
|
|
|
UpgradeScriptInfoToTextEncoding(smSystemScript,
|
|
|
|
kTextLanguageDontCare,
|
|
|
|
kTextRegionDontCare, NULL,
|
|
|
|
&enc) == noErr &&
|
|
|
|
CreateTextToUnicodeInfoByEncoding(enc, &scrap_to_uni) ==
|
|
|
|
noErr) {
|
|
|
|
err = ConvertFromTextToUnicode(scrap_to_uni, textlen,
|
|
|
|
*texth, 0, 0, NULL, NULL, NULL,
|
|
|
|
textlen * 2,
|
|
|
|
&iread, &olen, data);
|
|
|
|
DisposeTextToUnicodeInfo(&scrap_to_uni);
|
|
|
|
if (err == noErr) {
|
|
|
|
*p = data;
|
|
|
|
*lenp = olen / sizeof(**p);
|
|
|
|
} else {
|
|
|
|
*p = NULL;
|
|
|
|
*lenp = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
charset =
|
|
|
|
charset_from_macenc(GetScriptManagerVariable(smSysScript),
|
|
|
|
GetScriptManagerVariable(smRegionCode),
|
|
|
|
mac_gestalts.sysvers, NULL);
|
|
|
|
if (charset != CS_NONE) {
|
|
|
|
tptr = *texth;
|
|
|
|
*lenp = charset_to_unicode(&tptr, &textlen, data,
|
|
|
|
textlen * 2, charset, NULL,
|
|
|
|
NULL, 0);
|
|
|
|
}
|
|
|
|
*p = data;
|
|
|
|
}
|
|
|
|
DisposeHandle(texth);
|
2002-11-19 02:13:46 +00:00
|
|
|
} else {
|
|
|
|
*p = NULL;
|
|
|
|
*lenp = 0;
|
|
|
|
}
|
2003-01-25 19:23:03 +00:00
|
|
|
}
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
static pascal void mac_scrolltracker(ControlHandle control, short part)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s;
|
|
|
|
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
2003-02-04 23:39:26 +00:00
|
|
|
s = mac_windowsession(GetControlOwner(control));
|
2003-02-04 01:53:50 +00:00
|
|
|
#else
|
2003-02-04 23:39:26 +00:00
|
|
|
s = mac_windowsession((*control)->contrlOwner);
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
switch (part) {
|
|
|
|
case kControlUpButtonPart:
|
|
|
|
term_scroll(s->term, 0, -1);
|
|
|
|
break;
|
|
|
|
case kControlDownButtonPart:
|
|
|
|
term_scroll(s->term, 0, +1);
|
|
|
|
break;
|
|
|
|
case kControlPageUpPart:
|
|
|
|
term_scroll(s->term, 0, -(s->term->rows - 1));
|
|
|
|
break;
|
|
|
|
case kControlPageDownPart:
|
|
|
|
term_scroll(s->term, 0, +(s->term->rows - 1));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_keyterm(WindowPtr window, EventRecord *event)
|
|
|
|
{
|
2003-02-04 23:39:26 +00:00
|
|
|
Session *s = mac_windowsession(window);
|
2003-01-27 00:39:01 +00:00
|
|
|
Key_Sym keysym = PK_NULL;
|
|
|
|
unsigned int mods = 0, flags = PKF_NUMLOCK;
|
2003-02-04 00:01:33 +00:00
|
|
|
UniChar utxt[1];
|
|
|
|
char txt[1];
|
|
|
|
size_t len = 0;
|
|
|
|
ScriptCode key_script;
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2002-11-23 14:22:11 +00:00
|
|
|
ObscureCursor();
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-01-28 00:35:54 +00:00
|
|
|
#if 0
|
2003-01-27 00:39:01 +00:00
|
|
|
fprintf(stderr, "Got key event %08x\n", event->message);
|
2003-01-28 00:35:54 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
|
|
|
|
/* No meta key yet -- that'll be rather fun. */
|
|
|
|
|
|
|
|
/* Keys that we handle locally */
|
|
|
|
if (event->modifiers & shiftKey) {
|
2003-01-27 00:39:01 +00:00
|
|
|
switch ((event->message & keyCodeMask) >> 8) {
|
|
|
|
case 0x74: /* shift-pageup */
|
2002-11-19 02:13:46 +00:00
|
|
|
term_scroll(s->term, 0, -(s->term->rows - 1));
|
2003-01-27 00:39:01 +00:00
|
|
|
return;
|
|
|
|
case 0x79: /* shift-pagedown */
|
2002-11-19 02:13:46 +00:00
|
|
|
term_scroll(s->term, 0, +(s->term->rows - 1));
|
2003-01-27 00:39:01 +00:00
|
|
|
return;
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-27 00:39:01 +00:00
|
|
|
if (event->modifiers & shiftKey)
|
|
|
|
mods |= PKM_SHIFT;
|
|
|
|
if (event->modifiers & controlKey)
|
|
|
|
mods |= PKM_CONTROL;
|
|
|
|
if (event->what == autoKey)
|
|
|
|
flags |= PKF_REPEAT;
|
|
|
|
|
|
|
|
/* Mac key events consist of a virtual key code and a character code. */
|
|
|
|
|
|
|
|
switch ((event->message & keyCodeMask) >> 8) {
|
|
|
|
case 0x24: keysym = PK_RETURN; break;
|
|
|
|
case 0x30: keysym = PK_TAB; break;
|
|
|
|
case 0x33: keysym = PK_BACKSPACE; break;
|
|
|
|
case 0x35: keysym = PK_ESCAPE; break;
|
|
|
|
|
|
|
|
case 0x7A: keysym = PK_F1; break;
|
|
|
|
case 0x78: keysym = PK_F2; break;
|
|
|
|
case 0x63: keysym = PK_F3; break;
|
|
|
|
case 0x76: keysym = PK_F4; break;
|
|
|
|
case 0x60: keysym = PK_F5; break;
|
|
|
|
case 0x61: keysym = PK_F6; break;
|
|
|
|
case 0x62: keysym = PK_F7; break;
|
|
|
|
case 0x64: keysym = PK_F8; break;
|
|
|
|
case 0x65: keysym = PK_F9; break;
|
|
|
|
case 0x6D: keysym = PK_F10; break;
|
|
|
|
case 0x67: keysym = PK_F11; break;
|
|
|
|
case 0x6F: keysym = PK_F12; break;
|
|
|
|
case 0x69: keysym = PK_F13; break;
|
|
|
|
case 0x6B: keysym = PK_F14; break;
|
|
|
|
case 0x71: keysym = PK_F15; break;
|
|
|
|
|
|
|
|
case 0x72: keysym = PK_INSERT; break;
|
|
|
|
case 0x73: keysym = PK_HOME; break;
|
|
|
|
case 0x74: keysym = PK_PAGEUP; break;
|
|
|
|
case 0x75: keysym = PK_DELETE; break;
|
|
|
|
case 0x77: keysym = PK_END; break;
|
|
|
|
case 0x79: keysym = PK_PAGEDOWN; break;
|
|
|
|
|
|
|
|
case 0x47: keysym = PK_PF1; break;
|
|
|
|
case 0x51: keysym = PK_PF2; break;
|
|
|
|
case 0x4B: keysym = PK_PF3; break;
|
|
|
|
case 0x43: keysym = PK_PF4; break;
|
|
|
|
case 0x4E: keysym = PK_KPMINUS; break;
|
|
|
|
case 0x45: keysym = PK_KPCOMMA; break;
|
|
|
|
case 0x41: keysym = PK_KPDECIMAL; break;
|
|
|
|
case 0x4C: keysym = PK_KPENTER; break;
|
|
|
|
case 0x52: keysym = PK_KP0; break;
|
|
|
|
case 0x53: keysym = PK_KP1; break;
|
|
|
|
case 0x54: keysym = PK_KP2; break;
|
|
|
|
case 0x55: keysym = PK_KP3; break;
|
|
|
|
case 0x56: keysym = PK_KP4; break;
|
|
|
|
case 0x57: keysym = PK_KP5; break;
|
|
|
|
case 0x58: keysym = PK_KP6; break;
|
|
|
|
case 0x59: keysym = PK_KP7; break;
|
|
|
|
case 0x5B: keysym = PK_KP8; break;
|
|
|
|
case 0x5C: keysym = PK_KP9; break;
|
|
|
|
|
|
|
|
case 0x7B: keysym = PK_LEFT; break;
|
|
|
|
case 0x7C: keysym = PK_RIGHT; break;
|
|
|
|
case 0x7D: keysym = PK_DOWN; break;
|
|
|
|
case 0x7E: keysym = PK_UP; break;
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
2003-02-04 00:01:33 +00:00
|
|
|
/* Map from key script to Unicode. */
|
|
|
|
txt[0] = event->message & charCodeMask;
|
|
|
|
key_script = GetScriptManagerVariable(smKeyScript);
|
|
|
|
|
|
|
|
if (mac_gestalts.encvvers != 0) {
|
|
|
|
static TextToUnicodeInfo key_to_uni = NULL;
|
|
|
|
static ScriptCode key_to_uni_script;
|
|
|
|
TextEncoding enc;
|
|
|
|
ByteCount iread, olen;
|
|
|
|
OSErr err;
|
|
|
|
|
|
|
|
if (key_to_uni != NULL && key_to_uni_script != key_script)
|
|
|
|
DisposeTextToUnicodeInfo(&key_to_uni);
|
|
|
|
if (key_to_uni == NULL || key_to_uni_script != key_script) {
|
|
|
|
if (UpgradeScriptInfoToTextEncoding(key_script,
|
|
|
|
kTextLanguageDontCare,
|
|
|
|
kTextRegionDontCare, NULL,
|
|
|
|
&enc) == noErr &&
|
|
|
|
CreateTextToUnicodeInfoByEncoding(enc, &key_to_uni) == noErr)
|
|
|
|
key_to_uni_script = key_script;
|
|
|
|
else
|
|
|
|
key_to_uni = NULL;
|
|
|
|
}
|
|
|
|
if (key_to_uni != NULL) {
|
|
|
|
err = ConvertFromTextToUnicode(key_to_uni, 1, txt,
|
|
|
|
(kUnicodeKeepInfoMask |
|
|
|
|
kUnicodeStringUnterminatedMask),
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
sizeof(utxt), &iread, &olen, utxt);
|
|
|
|
if (err == noErr)
|
|
|
|
len = olen / sizeof(*utxt);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int charset;
|
|
|
|
char *tptr = txt;
|
|
|
|
int tlen = 1;
|
|
|
|
|
|
|
|
charset = charset_from_macenc(key_script,
|
|
|
|
GetScriptManagerVariable(smRegionCode),
|
|
|
|
mac_gestalts.sysvers, NULL);
|
|
|
|
if (charset != CS_NONE) {
|
|
|
|
len = charset_to_unicode(&tptr, &tlen, utxt, sizeof(utxt), charset,
|
|
|
|
NULL, NULL, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
term_key(s->term, keysym, utxt, len, mods, flags);
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void request_paste(void *frontend)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In the Mac OS, pasting is synchronous: we can read the
|
|
|
|
* clipboard with no difficulty, so request_paste() can just go
|
|
|
|
* ahead and paste.
|
|
|
|
*/
|
|
|
|
term_do_paste(s->term);
|
|
|
|
}
|
|
|
|
|
2002-12-08 01:17:31 +00:00
|
|
|
static struct {
|
|
|
|
Rect msgrect;
|
|
|
|
Point msgorigin;
|
2003-01-04 00:48:13 +00:00
|
|
|
Point zeromouse;
|
2002-12-08 01:17:31 +00:00
|
|
|
Session *s;
|
|
|
|
char oldmsg[20];
|
|
|
|
} growterm_state;
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_growterm(WindowPtr window, EventRecord *event)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Rect limits;
|
|
|
|
long grow_result;
|
|
|
|
int newrows, newcols;
|
|
|
|
Session *s;
|
2003-02-04 01:53:50 +00:00
|
|
|
#if !TARGET_API_MAC_CARBON
|
2002-12-08 01:17:31 +00:00
|
|
|
DragGrayRgnUPP draghooksave;
|
|
|
|
GrafPtr portsave;
|
|
|
|
FontInfo fi;
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-02-04 23:39:26 +00:00
|
|
|
s = mac_windowsession(window);
|
2002-12-08 01:17:31 +00:00
|
|
|
|
2003-02-04 01:53:50 +00:00
|
|
|
#if !TARGET_API_MAC_CARBON
|
2002-12-08 01:17:31 +00:00
|
|
|
draghooksave = LMGetDragHook();
|
|
|
|
growterm_state.oldmsg[0] = '\0';
|
2003-01-04 00:48:13 +00:00
|
|
|
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;
|
2002-12-08 01:17:31 +00:00
|
|
|
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));
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-12-08 01:17:31 +00:00
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
SetRect(&limits, s->font_width + 15, s->font_height, SHRT_MAX, SHRT_MAX);
|
|
|
|
grow_result = GrowWindow(window, event->where, &limits);
|
2002-12-08 01:17:31 +00:00
|
|
|
|
2003-02-04 01:53:50 +00:00
|
|
|
#if !TARGET_API_MAC_CARBON
|
2002-12-08 01:17:31 +00:00
|
|
|
DisposeDragGrayRgnUPP(LMGetDragHook());
|
|
|
|
LMSetDragHook(draghooksave);
|
|
|
|
InvalRect(&growterm_state.msgrect);
|
|
|
|
|
|
|
|
SetPort(portsave);
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-12-08 01:17:31 +00:00
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
if (grow_result != 0) {
|
|
|
|
newrows = HiWord(grow_result) / s->font_height;
|
|
|
|
newcols = (LoWord(grow_result) - 15) / s->font_width;
|
|
|
|
mac_adjustsize(s, newrows, newcols);
|
|
|
|
term_size(s->term, newrows, newcols, s->cfg.savelines);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-02-04 01:53:50 +00:00
|
|
|
#if !TARGET_API_MAC_CARBON
|
2002-12-08 01:17:31 +00:00
|
|
|
static pascal void mac_growtermdraghook(void)
|
|
|
|
{
|
|
|
|
Session *s = growterm_state.s;
|
|
|
|
GrafPtr portsave;
|
|
|
|
Point mouse;
|
|
|
|
char buf[20];
|
2003-01-09 22:45:48 +00:00
|
|
|
unsigned char pbuf[20];
|
2002-12-08 01:17:31 +00:00
|
|
|
int newrows, newcols;
|
|
|
|
|
|
|
|
GetMouse(&mouse);
|
2003-01-04 00:48:13 +00:00
|
|
|
newrows = (mouse.v - growterm_state.zeromouse.v) / s->font_height;
|
2002-12-08 01:17:31 +00:00
|
|
|
if (newrows < 1) newrows = 1;
|
2003-01-04 00:48:13 +00:00
|
|
|
newcols = (mouse.h - growterm_state.zeromouse.h) / s->font_width;
|
2002-12-08 01:17:31 +00:00
|
|
|
if (newcols < 1) newcols = 1;
|
|
|
|
sprintf(buf, "%dx%d", newcols, newrows);
|
|
|
|
if (strcmp(buf, growterm_state.oldmsg) == 0)
|
|
|
|
return;
|
|
|
|
strcpy(growterm_state.oldmsg, buf);
|
2003-01-09 22:45:48 +00:00
|
|
|
c2pstrcpy(pbuf, buf);
|
2002-12-08 01:17:31 +00:00
|
|
|
|
|
|
|
GetPort(&portsave);
|
|
|
|
SetPort(growterm_state.s->window);
|
|
|
|
EraseRect(&growterm_state.msgrect);
|
|
|
|
MoveTo(growterm_state.msgorigin.h, growterm_state.msgorigin.v);
|
2003-01-09 22:45:48 +00:00
|
|
|
DrawString(pbuf);
|
2002-12-08 01:17:31 +00:00
|
|
|
SetPort(portsave);
|
|
|
|
}
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-12-08 01:17:31 +00:00
|
|
|
|
2003-01-15 23:30:21 +00:00
|
|
|
void mac_closeterm(WindowPtr window)
|
|
|
|
{
|
2003-02-04 23:39:26 +00:00
|
|
|
Session *s = mac_windowsession(window);
|
2003-01-15 23:30:21 +00:00
|
|
|
|
|
|
|
/* 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);
|
2003-02-07 01:38:12 +00:00
|
|
|
mac_freeeventlog(s);
|
2003-02-04 23:39:26 +00:00
|
|
|
sfree((WinInfo *)GetWRefCon(s->window));
|
2003-01-15 23:30:21 +00:00
|
|
|
DisposeWindow(s->window);
|
|
|
|
DisposePalette(s->palette);
|
|
|
|
sfree(s);
|
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_activateterm(WindowPtr window, EventRecord *event)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s;
|
2003-02-15 16:22:15 +00:00
|
|
|
Boolean active = (event->modifiers & activeFlag) != 0;
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-02-04 23:39:26 +00:00
|
|
|
s = mac_windowsession(window);
|
2004-11-27 19:34:45 +00:00
|
|
|
term_set_focus(s->term, active);
|
2002-11-19 02:13:46 +00:00
|
|
|
term_update(s->term);
|
|
|
|
if (active)
|
|
|
|
ShowControl(s->scrollbar);
|
|
|
|
else {
|
|
|
|
if (HAVE_COLOR_QD())
|
|
|
|
PmBackColor(DEFAULT_BG);/* HideControl clears behind the control */
|
|
|
|
else
|
|
|
|
BackColor(blackColor);
|
|
|
|
HideControl(s->scrollbar);
|
|
|
|
}
|
|
|
|
mac_drawgrowicon(s);
|
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_updateterm(WindowPtr window)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s;
|
2003-02-04 01:53:50 +00:00
|
|
|
Rect bbox;
|
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
RgnHandle visrgn;
|
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-02-04 23:39:26 +00:00
|
|
|
s = mac_windowsession(window);
|
2003-02-04 02:03:53 +00:00
|
|
|
SetPort((GrafPtr)GetWindowPort(window));
|
2002-11-19 02:13:46 +00:00
|
|
|
BeginUpdate(window);
|
|
|
|
pre_paint(s);
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
visrgn = NewRgn();
|
|
|
|
GetPortVisibleRegion(GetWindowPort(window), visrgn);
|
|
|
|
GetRegionBounds(visrgn, &bbox);
|
|
|
|
#else
|
|
|
|
bbox = (*window->visRgn)->rgnBBox;
|
|
|
|
#endif
|
|
|
|
term_paint(s->term, s, PTOCC(bbox.left), PTOCR(bbox.top),
|
|
|
|
PTOCC(bbox.right), PTOCR(bbox.bottom), 1);
|
2002-11-19 02:13:46 +00:00
|
|
|
/* Restore default colours in case the Window Manager uses them */
|
|
|
|
if (HAVE_COLOR_QD()) {
|
|
|
|
PmForeColor(DEFAULT_FG);
|
|
|
|
PmBackColor(DEFAULT_BG);
|
|
|
|
} else {
|
|
|
|
ForeColor(whiteColor);
|
|
|
|
BackColor(blackColor);
|
|
|
|
}
|
|
|
|
if (FrontWindow() != window)
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
EraseRect(GetControlBounds(s->scrollbar, &bbox));
|
|
|
|
UpdateControls(window, visrgn);
|
|
|
|
DisposeRgn(visrgn);
|
|
|
|
#else
|
2002-11-19 02:13:46 +00:00
|
|
|
EraseRect(&(*s->scrollbar)->contrlRect);
|
|
|
|
UpdateControls(window, window->visRgn);
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
mac_drawgrowicon(s);
|
|
|
|
post_paint(s);
|
|
|
|
EndUpdate(window);
|
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
static void mac_drawgrowicon(Session *s)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Rect clip;
|
2002-11-28 21:02:07 +00:00
|
|
|
RgnHandle savergn;
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-02-04 02:03:53 +00:00
|
|
|
SetPort((GrafPtr)GetWindowPort(s->window));
|
2002-11-28 21:02:07 +00:00
|
|
|
/*
|
|
|
|
* Stop DrawGrowIcon giving us space for a horizontal scrollbar
|
|
|
|
* See Tech Note TB575 for details.
|
|
|
|
*/
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
GetPortBounds(GetWindowPort(s->window), &clip);
|
|
|
|
#else
|
2002-11-28 21:02:07 +00:00
|
|
|
clip = s->window->portRect;
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-28 21:02:07 +00:00
|
|
|
clip.left = clip.right - 15;
|
|
|
|
savergn = NewRgn();
|
|
|
|
GetClip(savergn);
|
2002-11-19 02:13:46 +00:00
|
|
|
ClipRect(&clip);
|
|
|
|
DrawGrowIcon(s->window);
|
2002-11-28 21:02:07 +00:00
|
|
|
SetClip(savergn);
|
|
|
|
DisposeRgn(savergn);
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct do_text_args {
|
|
|
|
Session *s;
|
|
|
|
Rect textrect;
|
|
|
|
char *text;
|
|
|
|
int len;
|
|
|
|
unsigned long attr;
|
|
|
|
int lattr;
|
2002-11-28 00:25:09 +00:00
|
|
|
Point numer, denom;
|
2002-11-19 02:13:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Call from the terminal emulator to draw a bit of text
|
|
|
|
*
|
|
|
|
* x and y are text row and column (zero-based)
|
|
|
|
*/
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
void do_text(Context ctx, int x, int y, wchar_t *text, int len,
|
2003-02-15 16:22:15 +00:00
|
|
|
unsigned long attr, int lattr)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s = ctx;
|
2003-02-01 15:44:08 +00:00
|
|
|
int style;
|
2002-11-19 02:13:46 +00:00
|
|
|
struct do_text_args a;
|
2003-01-14 18:43:26 +00:00
|
|
|
RgnHandle textrgn, saveclip;
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
RgnHandle visrgn;
|
|
|
|
#endif
|
2002-12-13 00:02:48 +00:00
|
|
|
char mactextbuf[1024];
|
2002-12-31 22:49:03 +00:00
|
|
|
wchar_t *unitextptr;
|
2005-01-21 00:02:59 +00:00
|
|
|
int fontwidth;
|
2002-12-31 22:49:03 +00:00
|
|
|
ByteCount iread, olen;
|
|
|
|
OSStatus err;
|
2003-02-04 01:53:50 +00:00
|
|
|
static DeviceLoopDrawingUPP do_text_for_device_upp = NULL;
|
2002-12-13 00:02:48 +00:00
|
|
|
|
|
|
|
assert(len <= 1024);
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2004-10-14 16:42:43 +00:00
|
|
|
/* SGT, 2004-10-14: I don't know how to support combining characters
|
|
|
|
* on the Mac. Hopefully the first person to fail this assertion will
|
|
|
|
* know how to do it better than me... */
|
|
|
|
assert(!(attr & TATTR_COMBINING));
|
|
|
|
|
2003-02-04 02:03:53 +00:00
|
|
|
SetPort((GrafPtr)GetWindowPort(s->window));
|
2003-01-14 18:43:26 +00:00
|
|
|
|
|
|
|
fontwidth = s->font_width;
|
|
|
|
if ((lattr & LATTR_MODE) != LATTR_NORM)
|
|
|
|
fontwidth *= 2;
|
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
/* First check this text is relevant */
|
|
|
|
a.textrect.top = y * s->font_height;
|
|
|
|
a.textrect.bottom = (y + 1) * s->font_height;
|
2003-01-14 18:43:26 +00:00
|
|
|
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;
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
visrgn = NewRgn();
|
|
|
|
GetPortVisibleRegion(GetWindowPort(s->window), visrgn);
|
|
|
|
if (!RectInRgn(&a.textrect, visrgn)) {
|
|
|
|
DisposeRgn(visrgn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DisposeRgn(visrgn);
|
|
|
|
#else
|
2002-11-19 02:13:46 +00:00
|
|
|
if (!RectInRgn(&a.textrect, s->window->visRgn))
|
|
|
|
return;
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2002-12-31 22:49:03 +00:00
|
|
|
if (s->uni_to_font != NULL) {
|
2002-12-13 00:02:48 +00:00
|
|
|
err = ConvertFromUnicodeToText(s->uni_to_font, len * sizeof(UniChar),
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
text, kUnicodeUseFallbacksMask,
|
2002-12-13 00:02:48 +00:00
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
1024, &iread, &olen, mactextbuf);
|
2002-12-31 22:49:03 +00:00
|
|
|
if (err != noErr && err != kTECUsedFallbacksStatus)
|
2003-01-02 00:33:40 +00:00
|
|
|
olen = 0;
|
2003-01-01 19:51:13 +00:00
|
|
|
} else if (s->font_charset != CS_NONE) {
|
2002-12-31 22:49:03 +00:00
|
|
|
/* XXX this is bogus if wchar_t and UniChar are different sizes. */
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
unitextptr = (wchar_t *)text;
|
2002-12-31 22:49:03 +00:00
|
|
|
olen = charset_from_unicode(&unitextptr, &len, mactextbuf, 1024,
|
2003-01-01 19:51:13 +00:00
|
|
|
s->font_charset, NULL, ".", 1);
|
|
|
|
} else
|
2003-01-02 00:33:40 +00:00
|
|
|
olen = 0;
|
2002-12-13 00:02:48 +00:00
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
a.s = s;
|
2002-12-31 22:49:03 +00:00
|
|
|
a.text = mactextbuf;
|
|
|
|
a.len = olen;
|
2002-11-19 02:13:46 +00:00
|
|
|
a.attr = attr;
|
|
|
|
a.lattr = lattr;
|
2003-01-14 18:43:26 +00:00
|
|
|
switch (lattr & LATTR_MODE) {
|
|
|
|
case LATTR_NORM:
|
2003-02-01 15:44:08 +00:00
|
|
|
TextSize(s->cfg.font.size);
|
2003-01-14 18:43:26 +00:00
|
|
|
a.numer = s->font_stdnumer;
|
|
|
|
a.denom = s->font_stddenom;
|
|
|
|
break;
|
|
|
|
case LATTR_WIDE:
|
2003-02-01 15:44:08 +00:00
|
|
|
TextSize(s->cfg.font.size);
|
2003-01-14 18:43:26 +00:00
|
|
|
a.numer = s->font_widenumer;
|
|
|
|
a.denom = s->font_widedenom;
|
|
|
|
break;
|
|
|
|
case LATTR_TOP:
|
|
|
|
case LATTR_BOT:
|
2003-02-01 15:44:08 +00:00
|
|
|
TextSize(s->cfg.font.size * 2);
|
2003-01-14 18:43:26 +00:00
|
|
|
a.numer = s->font_bignumer;
|
|
|
|
a.denom = s->font_bigdenom;
|
|
|
|
break;
|
|
|
|
}
|
2003-02-04 02:03:53 +00:00
|
|
|
SetPort((GrafPtr)GetWindowPort(s->window));
|
2002-11-19 02:13:46 +00:00
|
|
|
TextFont(s->fontnum);
|
2003-02-01 15:44:08 +00:00
|
|
|
style = s->cfg.font.face;
|
|
|
|
if ((attr & ATTR_BOLD) && !s->cfg.bold_colour)
|
2002-11-19 02:13:46 +00:00
|
|
|
style |= bold;
|
|
|
|
if (attr & ATTR_UNDER)
|
|
|
|
style |= underline;
|
|
|
|
TextFace(style);
|
2002-11-26 01:32:51 +00:00
|
|
|
TextMode(srcOr);
|
2002-11-19 02:13:46 +00:00
|
|
|
if (HAVE_COLOR_QD())
|
|
|
|
if (style & bold) {
|
|
|
|
SpaceExtra(s->font_boldadjust << 16);
|
|
|
|
CharExtra(s->font_boldadjust << 16);
|
|
|
|
} else {
|
|
|
|
SpaceExtra(0);
|
|
|
|
CharExtra(0);
|
|
|
|
}
|
2003-01-14 18:43:26 +00:00
|
|
|
saveclip = NewRgn();
|
|
|
|
GetClip(saveclip);
|
|
|
|
ClipRect(&a.textrect);
|
2002-11-19 02:13:46 +00:00
|
|
|
textrgn = NewRgn();
|
|
|
|
RectRgn(textrgn, &a.textrect);
|
2003-02-04 01:53:50 +00:00
|
|
|
if (HAVE_COLOR_QD()) {
|
|
|
|
if (do_text_for_device_upp == NULL)
|
|
|
|
do_text_for_device_upp =
|
|
|
|
NewDeviceLoopDrawingUPP(&do_text_for_device);
|
|
|
|
DeviceLoop(textrgn, do_text_for_device_upp, (long)&a, 0);
|
|
|
|
} else
|
2002-11-19 02:13:46 +00:00
|
|
|
do_text_for_device(1, 0, NULL, (long)&a);
|
2003-01-14 18:43:26 +00:00
|
|
|
SetClip(saveclip);
|
|
|
|
DisposeRgn(saveclip);
|
2002-11-19 02:13:46 +00:00
|
|
|
DisposeRgn(textrgn);
|
|
|
|
/* Tell the window manager about it in case this isn't an update */
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
ValidWindowRect(s->window, &a.textrect);
|
|
|
|
#else
|
2002-11-19 02:13:46 +00:00
|
|
|
ValidRect(&a.textrect);
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static pascal void do_text_for_device(short depth, short devflags,
|
2003-02-15 16:22:15 +00:00
|
|
|
GDHandle device, long cookie)
|
|
|
|
{
|
2003-02-04 02:03:53 +00:00
|
|
|
struct do_text_args *a = (struct do_text_args *)cookie;
|
2002-11-26 01:32:51 +00:00
|
|
|
int bgcolour, fgcolour, bright, reverse, tmp;
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
CQDProcsPtr gp = GetPortGrafProcs(GetWindowPort(a->s->window));
|
|
|
|
#else
|
|
|
|
QDProcsPtr gp = a->s->window->grafProcs;
|
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
|
|
|
|
bright = (a->attr & ATTR_BOLD) && a->s->cfg.bold_colour;
|
2002-11-26 01:32:51 +00:00
|
|
|
reverse = a->attr & ATTR_REVERSE;
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2002-11-26 01:32:51 +00:00
|
|
|
if (depth == 1 && (a->attr & TATTR_ACTCURS))
|
|
|
|
reverse = !reverse;
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2002-11-26 01:32:51 +00:00
|
|
|
if (HAVE_COLOR_QD()) {
|
|
|
|
if (depth > 2) {
|
2003-01-27 23:03:31 +00:00
|
|
|
fgcolour = ((a->attr & ATTR_FGMASK) >> ATTR_FGSHIFT);
|
2003-01-28 00:25:20 +00:00
|
|
|
bgcolour = ((a->attr & ATTR_BGMASK) >> ATTR_BGSHIFT);
|
2002-11-19 02:13:46 +00:00
|
|
|
} else {
|
2002-11-26 01:32:51 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
2002-11-26 01:32:51 +00:00
|
|
|
if (reverse) {
|
|
|
|
tmp = fgcolour;
|
|
|
|
fgcolour = bgcolour;
|
|
|
|
bgcolour = tmp;
|
|
|
|
}
|
|
|
|
if (bright && depth > 2)
|
2005-01-21 00:02:59 +00:00
|
|
|
if (fgcolour < 16) fgcolour |=8;
|
|
|
|
else if (fgcolour >= 256) fgcolour |=1;
|
2002-11-26 01:32:51 +00:00
|
|
|
if ((a->attr & TATTR_ACTCURS) && depth > 1) {
|
2002-11-19 23:59:27 +00:00
|
|
|
fgcolour = CURSOR_FG;
|
2002-11-19 02:13:46 +00:00
|
|
|
bgcolour = CURSOR_BG;
|
|
|
|
}
|
|
|
|
PmForeColor(fgcolour);
|
|
|
|
PmBackColor(bgcolour);
|
2002-11-26 01:32:51 +00:00
|
|
|
} 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);
|
|
|
|
}
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
2002-11-26 01:32:51 +00:00
|
|
|
EraseRect(&a->textrect);
|
2003-01-14 18:43:26 +00:00
|
|
|
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;
|
|
|
|
}
|
2002-11-19 02:13:46 +00:00
|
|
|
/* FIXME: Sort out bold width adjustments on Original QuickDraw. */
|
2003-02-04 01:53:50 +00:00
|
|
|
if (gp != NULL)
|
|
|
|
InvokeQDTextUPP(a->len, a->text, a->numer, a->denom, gp->textProc);
|
2002-11-28 00:25:09 +00:00
|
|
|
else
|
|
|
|
StdText(a->len, a->text, a->numer, a->denom);
|
2002-11-19 02:13:46 +00:00
|
|
|
|
|
|
|
if (a->attr & TATTR_PASCURS) {
|
|
|
|
PenNormal();
|
|
|
|
switch (depth) {
|
|
|
|
case 1:
|
|
|
|
PenMode(patXor);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
PmForeColor(CURSOR_BG);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
FrameRect(&a->textrect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-21 00:02:59 +00:00
|
|
|
void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
|
2002-11-19 02:13:46 +00:00
|
|
|
unsigned long attr, int lattr)
|
|
|
|
{
|
|
|
|
|
2002-11-19 23:59:27 +00:00
|
|
|
do_text(ctx, x, y, text, len, attr, lattr);
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Call from the terminal emulator to get its graphics context.
|
|
|
|
* Should probably be called start_redraw or something.
|
|
|
|
*/
|
2003-02-15 16:22:15 +00:00
|
|
|
void pre_paint(Session *s)
|
|
|
|
{
|
2002-11-29 00:32:03 +00:00
|
|
|
GDHandle gdh;
|
|
|
|
Rect myrect, tmprect;
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
RgnHandle visrgn;
|
|
|
|
#endif
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2002-11-29 00:32:03 +00:00
|
|
|
if (HAVE_COLOR_QD()) {
|
2002-12-09 22:49:56 +00:00
|
|
|
s->term->attr_mask = 0;
|
2003-02-04 02:03:53 +00:00
|
|
|
SetPort((GrafPtr)GetWindowPort(s->window));
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
visrgn = NewRgn();
|
|
|
|
GetPortVisibleRegion(GetWindowPort(s->window), visrgn);
|
|
|
|
GetRegionBounds(visrgn, &myrect);
|
|
|
|
DisposeRgn(visrgn);
|
|
|
|
#else
|
2002-11-29 00:32:03 +00:00
|
|
|
myrect = (*s->window->visRgn)->rgnBBox;
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-11-29 00:32:03 +00:00
|
|
|
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)
|
2002-12-09 22:49:56 +00:00
|
|
|
s->term->attr_mask |= ~(ATTR_COLOURS |
|
|
|
|
(s->cfg.bold_colour ? ATTR_BOLD : 0));
|
2002-12-08 22:23:08 +00:00
|
|
|
break;
|
2002-11-29 00:32:03 +00:00
|
|
|
case 2:
|
2002-12-08 22:23:08 +00:00
|
|
|
s->term->attr_mask |= ~ATTR_COLOURS;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
s->term->attr_mask = ~0;
|
|
|
|
return; /* No point checking more screens. */
|
2002-11-29 00:32:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else
|
2002-12-09 22:49:56 +00:00
|
|
|
s->term->attr_mask = ~(ATTR_COLOURS |
|
2002-11-29 00:32:03 +00:00
|
|
|
(s->cfg.bold_colour ? ATTR_BOLD : 0));
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
Context get_ctx(void *frontend)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s = frontend;
|
|
|
|
|
|
|
|
pre_paint(s);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2003-02-15 16:22:15 +00:00
|
|
|
void free_ctx(Context ctx)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Presumably this does something in Windows
|
|
|
|
*/
|
2003-02-15 16:22:15 +00:00
|
|
|
void post_paint(Session *s)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the scroll bar position
|
|
|
|
*
|
|
|
|
* total is the line number of the bottom of the working screen
|
|
|
|
* start is the line number of the top of the display
|
|
|
|
* page is the length of the displayed page
|
|
|
|
*/
|
2003-02-15 16:22:15 +00:00
|
|
|
void set_sbar(void *frontend, int total, int start, int page)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s = frontend;
|
|
|
|
|
|
|
|
/* We don't redraw until we've set everything up, to avoid glitches */
|
2003-02-04 01:53:50 +00:00
|
|
|
SetControlMinimum(s->scrollbar, 0);
|
|
|
|
SetControlMaximum(s->scrollbar, total - page);
|
2002-11-19 02:13:46 +00:00
|
|
|
SetControlValue(s->scrollbar, start);
|
2003-01-04 00:13:18 +00:00
|
|
|
#if !TARGET_CPU_68K
|
2002-11-19 02:13:46 +00:00
|
|
|
if (mac_gestalts.cntlattr & gestaltControlMgrPresent)
|
|
|
|
SetControlViewSize(s->scrollbar, page);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void sys_cursor(void *frontend, int x, int y)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* I think his is meaningless under Mac OS.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is still called when mode==BELL_VISUAL, even though the
|
|
|
|
* visual bell is handled entirely within terminal.c, because we
|
|
|
|
* may want to perform additional actions on any kind of bell (for
|
|
|
|
* example, taskbar flashing in Windows).
|
|
|
|
*/
|
|
|
|
void beep(void *frontend, int mode)
|
|
|
|
{
|
|
|
|
if (mode != BELL_VISUAL)
|
|
|
|
SysBeep(30);
|
|
|
|
/*
|
|
|
|
* XXX We should indicate the relevant window and/or use the
|
|
|
|
* Notification Manager
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
int char_width(Context ctx, int uc)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Until we support exciting character-set stuff, assume all chars are
|
|
|
|
* single-width.
|
|
|
|
*/
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set icon string -- a no-op here (Windowshade?)
|
|
|
|
*/
|
|
|
|
void set_icon(void *frontend, char *icon) {
|
|
|
|
Session *s = frontend;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the window title
|
|
|
|
*/
|
2003-02-15 16:22:15 +00:00
|
|
|
void set_title(void *frontend, char *title)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s = frontend;
|
|
|
|
Str255 mactitle;
|
|
|
|
|
2003-01-09 22:51:41 +00:00
|
|
|
c2pstrcpy(mactitle, title);
|
2002-11-19 02:13:46 +00:00
|
|
|
SetWTitle(s->window, mactitle);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* set or clear the "raw mouse message" mode
|
|
|
|
*/
|
|
|
|
void set_raw_mouse_mode(void *frontend, int activate)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
|
|
|
|
|
|
|
s->raw_mouse = activate;
|
|
|
|
/* FIXME: Should call mac_updatetermcursor as appropriate. */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Resize the window at the emulator's request
|
|
|
|
*/
|
2003-02-11 23:10:34 +00:00
|
|
|
void request_resize(void *frontend, int w, int h)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s = frontend;
|
2003-02-11 23:10:34 +00:00
|
|
|
RgnHandle grayrgn;
|
|
|
|
Rect graybox;
|
|
|
|
int wlim, hlim;
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-02-11 23:10:34 +00:00
|
|
|
/* Arbitrarily clip to the size of the desktop. */
|
|
|
|
grayrgn = GetGrayRgn();
|
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
GetRegionBounds(grayrgn, &graybox);
|
|
|
|
#else
|
|
|
|
graybox = (*grayrgn)->rgnBBox;
|
|
|
|
#endif
|
|
|
|
wlim = (graybox.right - graybox.left) / s->font_width;
|
|
|
|
hlim = (graybox.bottom - graybox.top) / s->font_height;
|
|
|
|
if (w > wlim) w = wlim;
|
|
|
|
if (h > hlim) h = hlim;
|
2003-01-14 15:24:51 +00:00
|
|
|
term_size(s->term, h, w, s->cfg.savelines);
|
2002-11-19 02:13:46 +00:00
|
|
|
mac_initfont(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Iconify (actually collapse) the window at the emulator's request.
|
|
|
|
*/
|
|
|
|
void set_iconic(void *frontend, int iconic)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
|
|
|
UInt32 features;
|
|
|
|
|
|
|
|
if (mac_gestalts.apprvers >= 0x0100 &&
|
|
|
|
GetWindowFeatures(s->window, &features) == noErr &&
|
|
|
|
(features & kWindowCanCollapse))
|
|
|
|
CollapseWindow(s->window, iconic);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move the window in response to a server-side request.
|
|
|
|
*/
|
|
|
|
void move_window(void *frontend, int x, int y)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
|
|
|
|
|
|
|
MoveWindow(s->window, x, y, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move the window to the top or bottom of the z-order in response
|
|
|
|
* to a server-side request.
|
|
|
|
*/
|
|
|
|
void set_zorder(void *frontend, int top)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We also change the input focus to point to the topmost window,
|
|
|
|
* since that's probably what the Human Interface Guidelines would
|
|
|
|
* like us to do.
|
|
|
|
*/
|
|
|
|
if (top)
|
|
|
|
SelectWindow(s->window);
|
|
|
|
else
|
|
|
|
SendBehind(s->window, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Refresh the window in response to a server-side request.
|
|
|
|
*/
|
|
|
|
void refresh_window(void *frontend)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
|
|
|
|
|
|
|
term_invalidate(s->term);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Maximise or restore the window in response to a server-side
|
|
|
|
* request.
|
|
|
|
*/
|
|
|
|
void set_zoomed(void *frontend, int zoomed)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
|
|
|
|
|
|
|
ZoomWindow(s->window, zoomed ? inZoomOut : inZoomIn, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report whether the window is iconic, for terminal reports.
|
|
|
|
*/
|
|
|
|
int is_iconic(void *frontend)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
|
|
|
UInt32 features;
|
|
|
|
|
|
|
|
if (mac_gestalts.apprvers >= 0x0100 &&
|
|
|
|
GetWindowFeatures(s->window, &features) == noErr &&
|
|
|
|
(features & kWindowCanCollapse))
|
|
|
|
return IsWindowCollapsed(s->window);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report the window's position, for terminal reports.
|
|
|
|
*/
|
|
|
|
void get_window_pos(void *frontend, int *x, int *y)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
2003-02-04 01:53:50 +00:00
|
|
|
Rect rect;
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
GetPortBounds(GetWindowPort(s->window), &rect);
|
|
|
|
#else
|
|
|
|
rect = s->window->portRect;
|
|
|
|
#endif
|
|
|
|
*x = rect.left;
|
|
|
|
*y = rect.top;
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report the window's pixel size, for terminal reports.
|
|
|
|
*/
|
|
|
|
void get_window_pixels(void *frontend, int *x, int *y)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
2003-02-04 01:53:50 +00:00
|
|
|
Rect rect;
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
GetPortBounds(GetWindowPort(s->window), &rect);
|
|
|
|
#else
|
|
|
|
rect = s->window->portRect;
|
|
|
|
#endif
|
|
|
|
*x = rect.right - rect.left;
|
|
|
|
*y = rect.bottom - rect.top;
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the window or icon title.
|
|
|
|
*/
|
|
|
|
char *get_window_title(void *frontend, int icon)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
2003-01-09 23:29:22 +00:00
|
|
|
Str255 ptitle;
|
|
|
|
static char title[256];
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-01-09 23:29:22 +00:00
|
|
|
GetWTitle(s->window, ptitle);
|
|
|
|
p2cstrcpy(title, ptitle);
|
|
|
|
return title;
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* real_palette_set(): This does the actual palette-changing work on behalf
|
|
|
|
* of palette_set(). Does _not_ call ActivatePalette() in case the caller
|
|
|
|
* is doing a batch of updates.
|
|
|
|
*/
|
|
|
|
static void real_palette_set(Session *s, int n, int r, int g, int b)
|
|
|
|
{
|
|
|
|
RGBColor col;
|
|
|
|
|
|
|
|
if (!HAVE_COLOR_QD())
|
|
|
|
return;
|
|
|
|
col.red = r * 0x0101;
|
|
|
|
col.green = g * 0x0101;
|
|
|
|
col.blue = b * 0x0101;
|
|
|
|
SetEntryColor(s->palette, n, &col);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the logical palette. Called by the terminal emulator.
|
|
|
|
*/
|
2003-02-15 16:22:15 +00:00
|
|
|
void palette_set(void *frontend, int n, int r, int g, int b)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s = frontend;
|
|
|
|
|
|
|
|
if (!HAVE_COLOR_QD())
|
|
|
|
return;
|
2005-01-21 00:02:59 +00:00
|
|
|
real_palette_set(s, n, r, g, b);
|
|
|
|
if (n == DEFAULT_BG)
|
|
|
|
mac_adjustwinbg(s);
|
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
ActivatePalette(s->window);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset to the default palette
|
|
|
|
*/
|
2003-02-15 16:22:15 +00:00
|
|
|
void palette_reset(void *frontend)
|
|
|
|
{
|
2002-11-19 02:13:46 +00:00
|
|
|
Session *s = frontend;
|
|
|
|
/* This maps colour indices in cfg to those used in our palette. */
|
|
|
|
static const int ww[] = {
|
2005-01-21 00:02:59 +00:00
|
|
|
256, 257, 258, 259, 260, 261,
|
|
|
|
0, 8, 1, 9, 2, 10, 3, 11,
|
|
|
|
4, 12, 5, 13, 6, 14, 7, 15
|
2002-11-19 02:13:46 +00:00
|
|
|
};
|
2005-01-21 00:02:59 +00:00
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!HAVE_COLOR_QD())
|
|
|
|
return;
|
|
|
|
|
2005-01-21 00:02:59 +00:00
|
|
|
for (i = 0; i < 22; i++) {
|
|
|
|
int w = ww[i];
|
|
|
|
real_palette_set(s,w,
|
|
|
|
s->cfg.colours[i][0],
|
|
|
|
s->cfg.colours[i][1],
|
|
|
|
s->cfg.colours[i][2]);
|
2002-11-19 02:13:46 +00:00
|
|
|
}
|
2005-01-21 00:02:59 +00:00
|
|
|
for (i = 0; i < 240; i++) {
|
|
|
|
if (i < 216) {
|
|
|
|
int r = i / 36, g = (i / 6) % 6, b = i % 6;
|
|
|
|
real_palette_set(s,i+16,
|
|
|
|
r * 0x33,
|
|
|
|
g * 0x33,
|
|
|
|
b * 0x33);
|
|
|
|
} else {
|
|
|
|
int shade = i - 216;
|
|
|
|
shade = (shade + 1) * 0xFF / (240 - 216 + 1);
|
|
|
|
real_palette_set(s,i+16,shade,shade,shade);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
mac_adjustwinbg(s);
|
|
|
|
ActivatePalette(s->window);
|
|
|
|
/* Palette Manager will generate update events as required. */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Scroll the screen. (`lines' is +ve for scrolling forward, -ve
|
|
|
|
* for backward.)
|
|
|
|
*/
|
2003-02-15 16:22:15 +00:00
|
|
|
void do_scroll(Context ctx, int topline, int botline, int lines)
|
|
|
|
{
|
2003-02-01 12:26:33 +00:00
|
|
|
Session *s = ctx;
|
2002-11-19 02:13:46 +00:00
|
|
|
Rect r;
|
2002-12-07 15:21:56 +00:00
|
|
|
RgnHandle scrollrgn = NewRgn();
|
|
|
|
RgnHandle movedupdate = NewRgn();
|
|
|
|
RgnHandle update = NewRgn();
|
|
|
|
Point g2l = { 0, 0 };
|
2002-11-19 02:13:46 +00:00
|
|
|
|
2003-02-04 02:03:53 +00:00
|
|
|
SetPort((GrafPtr)GetWindowPort(s->window));
|
2002-12-07 15:21:56 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
GetWindowRegion(s->window, kWindowUpdateRgn, movedupdate);
|
|
|
|
#else
|
|
|
|
GetWindowUpdateRgn(s->window, movedupdate);
|
|
|
|
#endif
|
2002-12-07 15:21:56 +00:00
|
|
|
GlobalToLocal(&g2l);
|
|
|
|
OffsetRgn(movedupdate, g2l.h, g2l.v); /* Convert to local co-ords. */
|
|
|
|
SectRgn(scrollrgn, movedupdate, movedupdate); /* Clip scrolled section. */
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
ValidWindowRgn(s->window, movedupdate);
|
|
|
|
#else
|
2002-12-07 15:21:56 +00:00
|
|
|
ValidRgn(movedupdate);
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-12-07 15:21:56 +00:00
|
|
|
OffsetRgn(movedupdate, 0, -lines * s->font_height); /* Scroll it. */
|
|
|
|
|
2002-11-24 00:38:44 +00:00
|
|
|
PenNormal();
|
2002-11-19 02:13:46 +00:00
|
|
|
if (HAVE_COLOR_QD())
|
|
|
|
PmBackColor(DEFAULT_BG);
|
2002-11-28 00:25:09 +00:00
|
|
|
else
|
|
|
|
BackColor(blackColor); /* XXX make configurable */
|
2002-11-19 02:13:46 +00:00
|
|
|
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);
|
2002-12-07 15:21:56 +00:00
|
|
|
|
2003-02-04 01:53:50 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
InvalWindowRgn(s->window, update);
|
|
|
|
InvalWindowRgn(s->window, movedupdate);
|
|
|
|
#else
|
2002-11-19 02:13:46 +00:00
|
|
|
InvalRgn(update);
|
2002-12-07 15:21:56 +00:00
|
|
|
InvalRgn(movedupdate);
|
2003-02-04 01:53:50 +00:00
|
|
|
#endif
|
2002-12-07 15:21:56 +00:00
|
|
|
|
|
|
|
DisposeRgn(scrollrgn);
|
|
|
|
DisposeRgn(movedupdate);
|
2002-11-19 02:13:46 +00:00
|
|
|
DisposeRgn(update);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Dummy routine, only required in plink. */
|
|
|
|
void ldisc_update(void *frontend, int echo, int edit)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mac PuTTY doesn't support printing yet.
|
|
|
|
*/
|
|
|
|
printer_job *printer_start_job(char *printer)
|
|
|
|
{
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void printer_job_data(printer_job *pj, void *data, int len)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void printer_finish_job(printer_job *pj)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void frontend_keypress(void *handle)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Keypress termination in non-Close-On-Exit mode is not
|
|
|
|
* currently supported in PuTTY proper, because the window
|
|
|
|
* always has a perfectly good Close button anyway. So we do
|
|
|
|
* nothing here.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ask whether to wipe a session log file before writing to it.
|
|
|
|
* Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
|
|
|
|
*/
|
2003-02-01 12:54:40 +00:00
|
|
|
int askappend(void *frontend, Filename filename)
|
2002-11-19 02:13:46 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
/* FIXME: not implemented yet. */
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2003-04-12 21:06:34 +00:00
|
|
|
int from_backend(void *frontend, int is_stderr, const char *data, int len)
|
|
|
|
{
|
|
|
|
Session *s = frontend;
|
|
|
|
|
|
|
|
return term_data(s->term, is_stderr, data, len);
|
|
|
|
}
|
|
|
|
|
2002-11-19 02:13:46 +00:00
|
|
|
/*
|
|
|
|
* Emacs magic:
|
|
|
|
* Local Variables:
|
|
|
|
* c-file-style: "simon"
|
|
|
|
* End:
|
|
|
|
*/
|
|
|
|
|