2005-02-15 21:45:50 +00:00
|
|
|
/*
|
|
|
|
* osxwin.m: code to manage a session window in Mac OS X PuTTY.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
|
|
#include "putty.h"
|
|
|
|
#include "terminal.h"
|
|
|
|
#include "osxclass.h"
|
|
|
|
|
|
|
|
/* Colours come in two flavours: configurable, and xterm-extended. */
|
|
|
|
#define NCFGCOLOURS (lenof(((Config *)0)->colours))
|
|
|
|
#define NEXTCOLOURS 240 /* 216 colour-cube plus 24 shades of grey */
|
|
|
|
#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The key component of the per-session data is the SessionWindow
|
|
|
|
* class. A pointer to this is used as the frontend handle, to be
|
|
|
|
* passed to all the platform-independent subsystems that require
|
|
|
|
* one.
|
|
|
|
*/
|
|
|
|
|
|
|
|
@interface TerminalView : NSImageView
|
|
|
|
{
|
|
|
|
NSFont *font;
|
|
|
|
NSImage *image;
|
|
|
|
Terminal *term;
|
|
|
|
Config cfg;
|
|
|
|
NSColor *colours[NALLCOLOURS];
|
|
|
|
float fw, fasc, fdesc, fh;
|
|
|
|
}
|
|
|
|
- (void)drawStartFinish:(BOOL)start;
|
|
|
|
- (void)setColour:(int)n r:(float)r g:(float)g b:(float)b;
|
|
|
|
- (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y
|
|
|
|
attr:(unsigned long)attr lattr:(int)lattr;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation TerminalView
|
|
|
|
- (BOOL)isFlipped
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
- (id)initWithTerminal:(Terminal *)aTerm config:(Config)aCfg
|
|
|
|
{
|
|
|
|
float w, h;
|
|
|
|
|
|
|
|
self = [self initWithFrame:NSMakeRect(0,0,100,100)];
|
|
|
|
|
|
|
|
term = aTerm;
|
|
|
|
cfg = aCfg;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialise the fonts we're going to use.
|
|
|
|
*
|
|
|
|
* FIXME: for the moment I'm sticking with exactly one default font.
|
|
|
|
*/
|
|
|
|
font = [NSFont userFixedPitchFontOfSize:0];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now determine the size of the primary font.
|
|
|
|
*
|
|
|
|
* FIXME: If we have multiple fonts, we may need to set fasc
|
|
|
|
* and fdesc to the _maximum_ asc and desc out of all the
|
|
|
|
* fonts, _before_ adding them together to get fh.
|
|
|
|
*/
|
|
|
|
fw = [font widthOfString:@"A"];
|
|
|
|
fasc = [font ascender];
|
|
|
|
fdesc = -[font descender];
|
|
|
|
fh = fasc + fdesc;
|
|
|
|
fh = (int)fh + (fh > (int)fh); /* round up, ickily */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Use this to figure out the size of the terminal view.
|
|
|
|
*/
|
|
|
|
w = fw * term->cols;
|
|
|
|
h = fh * term->rows;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* And set our size and subimage.
|
|
|
|
*/
|
|
|
|
image = [[NSImage alloc] initWithSize:NSMakeSize(w,h)];
|
|
|
|
[image setFlipped:YES];
|
|
|
|
[self setImage:image];
|
|
|
|
[self setFrame:NSMakeRect(0,0,w,h)];
|
|
|
|
|
|
|
|
term_invalidate(term);
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
- (void)drawStartFinish:(BOOL)start
|
|
|
|
{
|
|
|
|
if (start)
|
|
|
|
[image lockFocus];
|
|
|
|
else
|
|
|
|
[image unlockFocus];
|
|
|
|
}
|
|
|
|
- (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y
|
|
|
|
attr:(unsigned long)attr lattr:(int)lattr
|
|
|
|
{
|
|
|
|
int nfg, nbg, rlen, widefactor;
|
|
|
|
float ox, oy, tw, th;
|
|
|
|
NSDictionary *attrdict;
|
|
|
|
|
|
|
|
/* FIXME: TATTR_COMBINING */
|
|
|
|
|
|
|
|
nfg = ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT);
|
|
|
|
nbg = ((attr & ATTR_BGMASK) >> ATTR_BGSHIFT);
|
|
|
|
if (attr & ATTR_REVERSE) {
|
|
|
|
int t = nfg;
|
|
|
|
nfg = nbg;
|
|
|
|
nbg = t;
|
|
|
|
}
|
2012-06-09 15:09:22 +00:00
|
|
|
if ((cfg.bold_style & 2) && (attr & ATTR_BOLD)) {
|
2005-02-15 21:45:50 +00:00
|
|
|
if (nfg < 16) nfg |= 8;
|
|
|
|
else if (nfg >= 256) nfg |= 1;
|
|
|
|
}
|
2012-06-09 15:09:22 +00:00
|
|
|
if ((cfg.bold_style & 2) && (attr & ATTR_BLINK)) {
|
2005-02-15 21:45:50 +00:00
|
|
|
if (nbg < 16) nbg |= 8;
|
|
|
|
else if (nbg >= 256) nbg |= 1;
|
|
|
|
}
|
|
|
|
if (attr & TATTR_ACTCURS) {
|
|
|
|
nfg = 260;
|
|
|
|
nbg = 261;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (attr & ATTR_WIDE) {
|
|
|
|
widefactor = 2;
|
|
|
|
/* FIXME: what do we actually have to do about wide characters? */
|
|
|
|
} else {
|
|
|
|
widefactor = 1;
|
|
|
|
}
|
|
|
|
|
2012-06-09 15:09:22 +00:00
|
|
|
/* FIXME: ATTR_BOLD if cfg.bold_style & 1 */
|
2005-02-15 21:45:50 +00:00
|
|
|
|
|
|
|
if ((lattr & LATTR_MODE) != LATTR_NORM) {
|
|
|
|
x *= 2;
|
|
|
|
if (x >= term->cols)
|
|
|
|
return;
|
|
|
|
if (x + len*2*widefactor > term->cols)
|
|
|
|
len = (term->cols-x)/2/widefactor;/* trim to LH half */
|
|
|
|
rlen = len * 2;
|
|
|
|
} else
|
|
|
|
rlen = len;
|
|
|
|
|
|
|
|
/* FIXME: how do we actually implement double-{width,height} lattrs? */
|
|
|
|
|
|
|
|
ox = x * fw;
|
|
|
|
oy = y * fh;
|
|
|
|
tw = rlen * widefactor * fw;
|
|
|
|
th = fh;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the clipping rectangle.
|
|
|
|
*/
|
|
|
|
[[NSGraphicsContext currentContext] saveGraphicsState];
|
|
|
|
[NSBezierPath clipRect:NSMakeRect(ox, oy, tw, th)];
|
|
|
|
|
|
|
|
attrdict = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
colours[nfg], NSForegroundColorAttributeName,
|
|
|
|
colours[nbg], NSBackgroundColorAttributeName,
|
|
|
|
font, NSFontAttributeName, nil];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create an NSString and draw it.
|
|
|
|
*
|
|
|
|
* Annoyingly, although our input is wchar_t which is four
|
|
|
|
* bytes wide on OS X and terminal.c supports 32-bit Unicode,
|
|
|
|
* we must convert into the two-byte type `unichar' to store in
|
|
|
|
* NSString, so we lose display capability for extra-BMP stuff
|
|
|
|
* at this point.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
NSString *string;
|
|
|
|
unichar *utext;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
utext = snewn(len, unichar);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
utext[i] = (text[i] >= 0x10000 ? 0xFFFD : text[i]);
|
|
|
|
|
|
|
|
string = [NSString stringWithCharacters:utext length:len];
|
|
|
|
[string drawAtPoint:NSMakePoint(ox, oy) withAttributes:attrdict];
|
|
|
|
|
|
|
|
sfree(utext);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Restore the graphics state from before the clipRect: call.
|
|
|
|
*/
|
|
|
|
[[NSGraphicsContext currentContext] restoreGraphicsState];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* And flag this area as needing display.
|
|
|
|
*/
|
|
|
|
[self setNeedsDisplayInRect:NSMakeRect(ox, oy, tw, th)];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setColour:(int)n r:(float)r g:(float)g b:(float)b
|
|
|
|
{
|
|
|
|
assert(n >= 0 && n < lenof(colours));
|
|
|
|
colours[n] = [[NSColor colorWithDeviceRed:r green:g blue:b alpha:1.0]
|
|
|
|
retain];
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation SessionWindow
|
|
|
|
- (id)initWithConfig:(Config)aCfg
|
|
|
|
{
|
|
|
|
NSRect rect = { {0,0}, {0,0} };
|
|
|
|
|
2005-02-17 18:34:24 +00:00
|
|
|
alert_ctx = NULL;
|
|
|
|
|
2005-02-15 21:45:50 +00:00
|
|
|
cfg = aCfg; /* structure copy */
|
|
|
|
|
|
|
|
init_ucs(&ucsdata, cfg.line_codepage, cfg.utf8_override,
|
|
|
|
CS_UTF8, cfg.vtmode);
|
|
|
|
term = term_init(&cfg, &ucsdata, self);
|
|
|
|
logctx = log_init(self, &cfg);
|
|
|
|
term_provide_logctx(term, logctx);
|
|
|
|
term_size(term, cfg.height, cfg.width, cfg.savelines);
|
|
|
|
|
|
|
|
termview = [[[TerminalView alloc] initWithTerminal:term config:cfg]
|
|
|
|
autorelease];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now work out the size of the window.
|
|
|
|
*/
|
|
|
|
rect = [termview frame];
|
|
|
|
rect.origin = NSMakePoint(0,0);
|
|
|
|
rect.size.width += 2 * cfg.window_border;
|
|
|
|
rect.size.height += 2 * cfg.window_border;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up a backend.
|
|
|
|
*/
|
2007-06-30 21:56:44 +00:00
|
|
|
back = backend_from_proto(cfg.protocol);
|
|
|
|
if (!back)
|
2005-02-15 21:45:50 +00:00
|
|
|
back = &pty_backend;
|
|
|
|
|
|
|
|
{
|
|
|
|
const char *error;
|
|
|
|
char *realhost = NULL;
|
|
|
|
error = back->init(self, &backhandle, &cfg, cfg.host, cfg.port,
|
|
|
|
&realhost, cfg.tcp_nodelay, cfg.tcp_keepalives);
|
|
|
|
if (error) {
|
|
|
|
fatalbox("%s\n", error); /* FIXME: connection_fatal at worst */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (realhost)
|
|
|
|
sfree(realhost); /* FIXME: do something with this */
|
|
|
|
}
|
2005-02-18 18:33:31 +00:00
|
|
|
back->provide_logctx(backhandle, logctx);
|
2005-02-15 21:45:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a line discipline. (This must be done after creating
|
|
|
|
* the terminal _and_ the backend, since it needs to be passed
|
|
|
|
* pointers to both.)
|
|
|
|
*/
|
|
|
|
ldisc = ldisc_create(&cfg, term, back, backhandle, self);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: Set up a scrollbar.
|
|
|
|
*/
|
|
|
|
|
|
|
|
self = [super initWithContentRect:rect
|
|
|
|
styleMask:(NSTitledWindowMask | NSMiniaturizableWindowMask |
|
|
|
|
NSClosableWindowMask)
|
|
|
|
backing:NSBackingStoreBuffered
|
|
|
|
defer:YES];
|
|
|
|
[self setTitle:@"PuTTY"];
|
|
|
|
|
|
|
|
[self setIgnoresMouseEvents:NO];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Put the terminal view in the window.
|
|
|
|
*/
|
|
|
|
rect = [termview frame];
|
|
|
|
rect.origin = NSMakePoint(cfg.window_border, cfg.window_border);
|
|
|
|
[termview setFrame:rect];
|
|
|
|
[[self contentView] addSubview:termview];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up the colour palette.
|
|
|
|
*/
|
|
|
|
palette_reset(self);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: Only the _first_ document window should be centred.
|
|
|
|
* The subsequent ones should appear down and to the right of
|
|
|
|
* it, probably using the cascade function provided by Cocoa.
|
|
|
|
* Also we're apparently required by the HIG to remember and
|
|
|
|
* reuse previous positions of windows, although I'm not sure
|
|
|
|
* how that works if the user opens more than one of the same
|
|
|
|
* session type.
|
|
|
|
*/
|
|
|
|
[self center]; /* :-) */
|
|
|
|
|
2005-02-26 13:37:07 +00:00
|
|
|
exited = FALSE;
|
|
|
|
|
2005-02-15 21:45:50 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* FIXME: Here we must deallocate all sorts of stuff: the
|
|
|
|
* terminal, the backend, the ldisc, the logctx, you name it.
|
|
|
|
* Do so.
|
|
|
|
*/
|
2005-02-17 18:34:24 +00:00
|
|
|
sfree(alert_ctx);
|
2005-02-26 13:37:07 +00:00
|
|
|
if (back)
|
|
|
|
back->free(backhandle);
|
|
|
|
if (ldisc)
|
|
|
|
ldisc_free(ldisc);
|
2005-02-26 15:13:13 +00:00
|
|
|
/* ldisc must be freed before term, since ldisc_free expects term
|
|
|
|
* still to be around. */
|
|
|
|
if (logctx)
|
|
|
|
log_free(logctx);
|
|
|
|
if (term)
|
|
|
|
term_free(term);
|
2005-02-15 21:45:50 +00:00
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)drawStartFinish:(BOOL)start
|
|
|
|
{
|
|
|
|
[termview drawStartFinish:start];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setColour:(int)n r:(float)r g:(float)g b:(float)b
|
|
|
|
{
|
|
|
|
[termview setColour:n r:r g:g b:b];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y
|
|
|
|
attr:(unsigned long)attr lattr:(int)lattr
|
|
|
|
{
|
|
|
|
/* Pass this straight on to the TerminalView. */
|
|
|
|
[termview doText:text len:len x:x y:y attr:attr lattr:lattr];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (Config *)cfg
|
|
|
|
{
|
|
|
|
return &cfg;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)keyDown:(NSEvent *)ev
|
|
|
|
{
|
|
|
|
NSString *s = [ev characters];
|
|
|
|
int i;
|
|
|
|
int n = [s length], c = [s characterAtIndex:0], m = [ev modifierFlags];
|
|
|
|
int cm = [[ev charactersIgnoringModifiers] characterAtIndex:0];
|
|
|
|
wchar_t output[32];
|
|
|
|
char coutput[32];
|
|
|
|
int use_coutput = FALSE, special = FALSE, start, end;
|
|
|
|
|
2005-02-26 13:37:07 +00:00
|
|
|
//printf("n=%d c=U+%04x cm=U+%04x m=%08x\n", n, c, cm, m);
|
2005-02-15 21:45:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: Alt+numberpad codes.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Shift and Ctrl with PageUp/PageDown for scrollback.
|
|
|
|
*/
|
|
|
|
if (n == 1 && c == NSPageUpFunctionKey && (m & NSShiftKeyMask)) {
|
|
|
|
term_scroll(term, 0, -term->rows/2);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (n == 1 && c == NSPageUpFunctionKey && (m & NSControlKeyMask)) {
|
|
|
|
term_scroll(term, 0, -1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (n == 1 && c == NSPageDownFunctionKey && (m & NSShiftKeyMask)) {
|
|
|
|
term_scroll(term, 0, +term->rows/2);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (n == 1 && c == NSPageDownFunctionKey && (m & NSControlKeyMask)) {
|
|
|
|
term_scroll(term, 0, +1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: Shift-Ins for paste? Or is that not Maccy enough?
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: Alt (Option? Command?) prefix in general.
|
|
|
|
*
|
|
|
|
* (Note that Alt-Shift-thing will work just by looking at
|
|
|
|
* charactersIgnoringModifiers; but Alt-Ctrl-thing will need
|
|
|
|
* processing properly, and Alt-as-in-Option won't happen at
|
|
|
|
* all. Hmmm.)
|
|
|
|
*
|
|
|
|
* (Note also that we need to be able to override menu key
|
|
|
|
* equivalents before this is particularly useful.)
|
|
|
|
*/
|
|
|
|
start = 1;
|
|
|
|
end = start;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ctrl-` is the same as Ctrl-\, unless we already have a
|
|
|
|
* better idea.
|
|
|
|
*/
|
|
|
|
if ((m & NSControlKeyMask) && n == 1 && cm == '`' && c == '`') {
|
|
|
|
output[1] = '\x1c';
|
|
|
|
end = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We handle Return ourselves, because it needs to be flagged as
|
|
|
|
* special to ldisc. */
|
|
|
|
if (n == 1 && c == '\015') {
|
|
|
|
coutput[1] = '\015';
|
|
|
|
use_coutput = TRUE;
|
|
|
|
end = 2;
|
|
|
|
special = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Control-Shift-Space is 160 (ISO8859 nonbreaking space) */
|
|
|
|
if (n == 1 && (m & NSControlKeyMask) && (m & NSShiftKeyMask) &&
|
|
|
|
cm == ' ') {
|
|
|
|
output[1] = '\240';
|
|
|
|
end = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Control-2, Control-Space and Control-@ are all NUL. */
|
|
|
|
if ((m & NSControlKeyMask) && n == 1 &&
|
|
|
|
(cm == '2' || cm == '@' || cm == ' ') && c == cm) {
|
|
|
|
output[1] = '\0';
|
|
|
|
end = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We don't let MacOS tell us what Backspace is! We know better. */
|
|
|
|
if (cm == 0x7F && !(m & NSShiftKeyMask)) {
|
|
|
|
coutput[1] = cfg.bksp_is_delete ? '\x7F' : '\x08';
|
|
|
|
end = 2;
|
|
|
|
use_coutput = special = TRUE;
|
|
|
|
}
|
|
|
|
/* For Shift Backspace, do opposite of what is configured. */
|
|
|
|
if (cm == 0x7F && (m & NSShiftKeyMask)) {
|
|
|
|
coutput[1] = cfg.bksp_is_delete ? '\x08' : '\x7F';
|
|
|
|
end = 2;
|
|
|
|
use_coutput = special = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Shift-Tab is ESC [ Z. Oddly, this combination generates ^Y by
|
|
|
|
* default on MacOS! */
|
|
|
|
if (cm == 0x19 && (m & NSShiftKeyMask) && !(m & NSControlKeyMask)) {
|
|
|
|
end = 1;
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = '[';
|
|
|
|
output[end++] = 'Z';
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NetHack keypad mode.
|
|
|
|
*/
|
|
|
|
if (cfg.nethack_keypad && (m & NSNumericPadKeyMask)) {
|
|
|
|
wchar_t *keys = NULL;
|
|
|
|
switch (cm) {
|
|
|
|
case '1': keys = L"bB"; break;
|
|
|
|
case '2': keys = L"jJ"; break;
|
|
|
|
case '3': keys = L"nN"; break;
|
|
|
|
case '4': keys = L"hH"; break;
|
|
|
|
case '5': keys = L".."; break;
|
|
|
|
case '6': keys = L"lL"; break;
|
|
|
|
case '7': keys = L"yY"; break;
|
|
|
|
case '8': keys = L"kK"; break;
|
|
|
|
case '9': keys = L"uU"; break;
|
|
|
|
}
|
|
|
|
if (keys) {
|
|
|
|
end = 2;
|
|
|
|
if (m & NSShiftKeyMask)
|
|
|
|
output[1] = keys[1];
|
|
|
|
else
|
|
|
|
output[1] = keys[0];
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Application keypad mode.
|
|
|
|
*/
|
|
|
|
if (term->app_keypad_keys && !cfg.no_applic_k &&
|
|
|
|
(m & NSNumericPadKeyMask)) {
|
|
|
|
int xkey = 0;
|
|
|
|
switch (cm) {
|
|
|
|
case NSClearLineFunctionKey: xkey = 'P'; break;
|
|
|
|
case '=': xkey = 'Q'; break;
|
|
|
|
case '/': xkey = 'R'; break;
|
|
|
|
case '*': xkey = 'S'; break;
|
|
|
|
/*
|
|
|
|
* FIXME: keypad - and + need to be mapped to ESC O l
|
|
|
|
* and ESC O k, or ESC O l and ESC O m, depending on
|
|
|
|
* xterm function key mode, and I can't remember which
|
|
|
|
* goes where.
|
|
|
|
*/
|
|
|
|
case '\003': xkey = 'M'; break;
|
|
|
|
case '0': xkey = 'p'; break;
|
|
|
|
case '1': xkey = 'q'; break;
|
|
|
|
case '2': xkey = 'r'; break;
|
|
|
|
case '3': xkey = 's'; break;
|
|
|
|
case '4': xkey = 't'; break;
|
|
|
|
case '5': xkey = 'u'; break;
|
|
|
|
case '6': xkey = 'v'; break;
|
|
|
|
case '7': xkey = 'w'; break;
|
|
|
|
case '8': xkey = 'x'; break;
|
|
|
|
case '9': xkey = 'y'; break;
|
|
|
|
case '.': xkey = 'n'; break;
|
|
|
|
}
|
|
|
|
if (xkey) {
|
|
|
|
if (term->vt52_mode) {
|
|
|
|
if (xkey >= 'P' && xkey <= 'S') {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = xkey;
|
|
|
|
} else {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = '?';
|
|
|
|
output[end++] = xkey;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = 'O';
|
|
|
|
output[end++] = xkey;
|
|
|
|
}
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Next, all the keys that do tilde codes. (ESC '[' nn '~',
|
|
|
|
* for integer decimal nn.)
|
|
|
|
*
|
|
|
|
* We also deal with the weird ones here. Linux VCs replace F1
|
|
|
|
* to F5 by ESC [ [ A to ESC [ [ E. rxvt doesn't do _that_, but
|
|
|
|
* does replace Home and End (1~ and 4~) by ESC [ H and ESC O w
|
|
|
|
* respectively.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
int code = 0;
|
|
|
|
switch (cm) {
|
|
|
|
case NSF1FunctionKey:
|
|
|
|
code = (m & NSShiftKeyMask ? 23 : 11);
|
|
|
|
break;
|
|
|
|
case NSF2FunctionKey:
|
|
|
|
code = (m & NSShiftKeyMask ? 24 : 12);
|
|
|
|
break;
|
|
|
|
case NSF3FunctionKey:
|
|
|
|
code = (m & NSShiftKeyMask ? 25 : 13);
|
|
|
|
break;
|
|
|
|
case NSF4FunctionKey:
|
|
|
|
code = (m & NSShiftKeyMask ? 26 : 14);
|
|
|
|
break;
|
|
|
|
case NSF5FunctionKey:
|
|
|
|
code = (m & NSShiftKeyMask ? 28 : 15);
|
|
|
|
break;
|
|
|
|
case NSF6FunctionKey:
|
|
|
|
code = (m & NSShiftKeyMask ? 29 : 17);
|
|
|
|
break;
|
|
|
|
case NSF7FunctionKey:
|
|
|
|
code = (m & NSShiftKeyMask ? 31 : 18);
|
|
|
|
break;
|
|
|
|
case NSF8FunctionKey:
|
|
|
|
code = (m & NSShiftKeyMask ? 32 : 19);
|
|
|
|
break;
|
|
|
|
case NSF9FunctionKey:
|
|
|
|
code = (m & NSShiftKeyMask ? 33 : 20);
|
|
|
|
break;
|
|
|
|
case NSF10FunctionKey:
|
|
|
|
code = (m & NSShiftKeyMask ? 34 : 21);
|
|
|
|
break;
|
|
|
|
case NSF11FunctionKey:
|
|
|
|
code = 23;
|
|
|
|
break;
|
|
|
|
case NSF12FunctionKey:
|
|
|
|
code = 24;
|
|
|
|
break;
|
|
|
|
case NSF13FunctionKey:
|
|
|
|
code = 25;
|
|
|
|
break;
|
|
|
|
case NSF14FunctionKey:
|
|
|
|
code = 26;
|
|
|
|
break;
|
|
|
|
case NSF15FunctionKey:
|
|
|
|
code = 28;
|
|
|
|
break;
|
|
|
|
case NSF16FunctionKey:
|
|
|
|
code = 29;
|
|
|
|
break;
|
|
|
|
case NSF17FunctionKey:
|
|
|
|
code = 31;
|
|
|
|
break;
|
|
|
|
case NSF18FunctionKey:
|
|
|
|
code = 32;
|
|
|
|
break;
|
|
|
|
case NSF19FunctionKey:
|
|
|
|
code = 33;
|
|
|
|
break;
|
|
|
|
case NSF20FunctionKey:
|
|
|
|
code = 34;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!(m & NSControlKeyMask)) switch (cm) {
|
|
|
|
case NSHomeFunctionKey:
|
|
|
|
code = 1;
|
|
|
|
break;
|
|
|
|
#ifdef FIXME
|
|
|
|
case GDK_Insert: case GDK_KP_Insert:
|
|
|
|
code = 2;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case NSDeleteFunctionKey:
|
|
|
|
code = 3;
|
|
|
|
break;
|
|
|
|
case NSEndFunctionKey:
|
|
|
|
code = 4;
|
|
|
|
break;
|
|
|
|
case NSPageUpFunctionKey:
|
|
|
|
code = 5;
|
|
|
|
break;
|
|
|
|
case NSPageDownFunctionKey:
|
|
|
|
code = 6;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Reorder edit keys to physical order */
|
|
|
|
if (cfg.funky_type == FUNKY_VT400 && code <= 6)
|
|
|
|
code = "\0\2\1\4\5\3\6"[code];
|
|
|
|
|
|
|
|
if (term->vt52_mode && code > 0 && code <= 6) {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = " HLMEIG"[code];
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cfg.funky_type == FUNKY_SCO && /* SCO function keys */
|
|
|
|
code >= 11 && code <= 34) {
|
|
|
|
char codes[] = "MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@[\\]^_`{";
|
|
|
|
int index = 0;
|
|
|
|
switch (cm) {
|
|
|
|
case NSF1FunctionKey: index = 0; break;
|
|
|
|
case NSF2FunctionKey: index = 1; break;
|
|
|
|
case NSF3FunctionKey: index = 2; break;
|
|
|
|
case NSF4FunctionKey: index = 3; break;
|
|
|
|
case NSF5FunctionKey: index = 4; break;
|
|
|
|
case NSF6FunctionKey: index = 5; break;
|
|
|
|
case NSF7FunctionKey: index = 6; break;
|
|
|
|
case NSF8FunctionKey: index = 7; break;
|
|
|
|
case NSF9FunctionKey: index = 8; break;
|
|
|
|
case NSF10FunctionKey: index = 9; break;
|
|
|
|
case NSF11FunctionKey: index = 10; break;
|
|
|
|
case NSF12FunctionKey: index = 11; break;
|
|
|
|
}
|
|
|
|
if (m & NSShiftKeyMask) index += 12;
|
|
|
|
if (m & NSControlKeyMask) index += 24;
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = '[';
|
|
|
|
output[end++] = codes[index];
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (cfg.funky_type == FUNKY_SCO && /* SCO small keypad */
|
|
|
|
code >= 1 && code <= 6) {
|
|
|
|
char codes[] = "HL.FIG";
|
|
|
|
if (code == 3) {
|
|
|
|
output[1] = '\x7F';
|
|
|
|
end = 2;
|
|
|
|
} else {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = '[';
|
|
|
|
output[end++] = codes[code-1];
|
|
|
|
}
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if ((term->vt52_mode || cfg.funky_type == FUNKY_VT100P) &&
|
|
|
|
code >= 11 && code <= 24) {
|
|
|
|
int offt = 0;
|
|
|
|
if (code > 15)
|
|
|
|
offt++;
|
|
|
|
if (code > 21)
|
|
|
|
offt++;
|
|
|
|
if (term->vt52_mode) {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = code + 'P' - 11 - offt;
|
|
|
|
} else {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = 'O';
|
|
|
|
output[end++] = code + 'P' - 11 - offt;
|
|
|
|
}
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (cfg.funky_type == FUNKY_LINUX && code >= 11 && code <= 15) {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = '[';
|
|
|
|
output[end++] = '[';
|
|
|
|
output[end++] = code + 'A' - 11;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (cfg.funky_type == FUNKY_XTERM && code >= 11 && code <= 14) {
|
|
|
|
if (term->vt52_mode) {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = code + 'P' - 11;
|
|
|
|
} else {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = 'O';
|
|
|
|
output[end++] = code + 'P' - 11;
|
|
|
|
}
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (cfg.rxvt_homeend && (code == 1 || code == 4)) {
|
|
|
|
if (code == 1) {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = '[';
|
|
|
|
output[end++] = 'H';
|
|
|
|
} else {
|
|
|
|
output[end++] = '\033';
|
|
|
|
output[end++] = 'O';
|
|
|
|
output[end++] = 'w';
|
|
|
|
}
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (code) {
|
|
|
|
char buf[20];
|
|
|
|
sprintf(buf, "\x1B[%d~", code);
|
|
|
|
for (i = 0; buf[i]; i++)
|
|
|
|
output[end++] = buf[i];
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Cursor keys. (This includes the numberpad cursor keys,
|
|
|
|
* if we haven't already done them due to app keypad mode.)
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
int xkey = 0;
|
|
|
|
switch (cm) {
|
|
|
|
case NSUpArrowFunctionKey: xkey = 'A'; break;
|
|
|
|
case NSDownArrowFunctionKey: xkey = 'B'; break;
|
|
|
|
case NSRightArrowFunctionKey: xkey = 'C'; break;
|
|
|
|
case NSLeftArrowFunctionKey: xkey = 'D'; break;
|
|
|
|
}
|
|
|
|
if (xkey) {
|
2010-03-06 15:50:26 +00:00
|
|
|
end += format_arrow_key(output+end, term, xkey,
|
|
|
|
m & NSControlKeyMask);
|
2005-02-15 21:45:50 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Failing everything else, send the exact Unicode we got from
|
|
|
|
* OS X.
|
|
|
|
*/
|
|
|
|
if (end == start) {
|
|
|
|
if (n > lenof(output)-start)
|
|
|
|
n = lenof(output)-start; /* _shouldn't_ happen! */
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
output[i+start] = [s characterAtIndex:i];
|
|
|
|
}
|
|
|
|
end = n+start;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (use_coutput) {
|
|
|
|
assert(special);
|
|
|
|
assert(end < lenof(coutput));
|
|
|
|
coutput[end] = '\0';
|
|
|
|
ldisc_send(ldisc, coutput+start, -2, TRUE);
|
|
|
|
} else {
|
|
|
|
luni_send(ldisc, output+start, end-start, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int)fromBackend:(const char *)data len:(int)len isStderr:(int)is_stderr
|
|
|
|
{
|
|
|
|
return term_data(term, is_stderr, data, len);
|
|
|
|
}
|
|
|
|
|
2007-02-18 15:59:38 +00:00
|
|
|
- (int)fromBackendUntrusted:(const char *)data len:(int)len
|
|
|
|
{
|
|
|
|
return term_data_untrusted(term, data, len);
|
|
|
|
}
|
|
|
|
|
2005-02-17 18:34:24 +00:00
|
|
|
- (void)startAlert:(NSAlert *)alert
|
|
|
|
withCallback:(void (*)(void *, int))callback andCtx:(void *)ctx
|
|
|
|
{
|
2005-02-18 18:33:31 +00:00
|
|
|
if (alert_ctx || alert_qhead) {
|
|
|
|
/*
|
|
|
|
* Queue this alert to be shown later.
|
|
|
|
*/
|
|
|
|
struct alert_queue *qitem = snew(struct alert_queue);
|
|
|
|
qitem->next = NULL;
|
|
|
|
qitem->alert = alert;
|
|
|
|
qitem->callback = callback;
|
|
|
|
qitem->ctx = ctx;
|
|
|
|
if (alert_qtail)
|
|
|
|
alert_qtail->next = qitem;
|
|
|
|
else
|
|
|
|
alert_qhead = qitem;
|
|
|
|
alert_qtail = qitem;
|
|
|
|
} else {
|
|
|
|
alert_callback = callback;
|
|
|
|
alert_ctx = ctx; /* NB this is assumed to need freeing! */
|
|
|
|
[alert beginSheetModalForWindow:self modalDelegate:self
|
|
|
|
didEndSelector:@selector(alertSheetDidEnd:returnCode:contextInfo:)
|
|
|
|
contextInfo:NULL];
|
|
|
|
}
|
2005-02-17 18:34:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)alertSheetDidEnd:(NSAlert *)alert returnCode:(int)returnCode
|
|
|
|
contextInfo:(void *)contextInfo
|
|
|
|
{
|
2005-02-17 18:56:37 +00:00
|
|
|
[self performSelectorOnMainThread:
|
|
|
|
@selector(alertSheetDidFinishEnding:)
|
|
|
|
withObject:[NSNumber numberWithInt:returnCode]
|
|
|
|
waitUntilDone:NO];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)alertSheetDidFinishEnding:(id)object
|
|
|
|
{
|
|
|
|
int returnCode = [object intValue];
|
2005-02-18 18:33:31 +00:00
|
|
|
|
|
|
|
alert_callback(alert_ctx, returnCode); /* transfers ownership of ctx */
|
2005-02-17 18:56:37 +00:00
|
|
|
|
|
|
|
/*
|
2005-02-18 18:33:31 +00:00
|
|
|
* If there's an alert in our queue (either already or because
|
|
|
|
* the callback just queued it), start it.
|
2005-02-17 18:56:37 +00:00
|
|
|
*/
|
2005-02-18 18:33:31 +00:00
|
|
|
if (alert_qhead) {
|
|
|
|
struct alert_queue *qnext;
|
|
|
|
|
|
|
|
alert_callback = alert_qhead->callback;
|
|
|
|
alert_ctx = alert_qhead->ctx;
|
|
|
|
[alert_qhead->alert beginSheetModalForWindow:self modalDelegate:self
|
|
|
|
didEndSelector:@selector(alertSheetDidEnd:returnCode:contextInfo:)
|
|
|
|
contextInfo:NULL];
|
|
|
|
|
|
|
|
qnext = alert_qhead->next;
|
|
|
|
sfree(alert_qhead);
|
|
|
|
alert_qhead = qnext;
|
|
|
|
if (!qnext)
|
|
|
|
alert_qtail = NULL;
|
|
|
|
} else {
|
|
|
|
alert_ctx = NULL;
|
|
|
|
}
|
2005-02-17 18:34:24 +00:00
|
|
|
}
|
|
|
|
|
2005-02-26 13:37:07 +00:00
|
|
|
- (void)notifyRemoteExit
|
|
|
|
{
|
|
|
|
int exitcode;
|
|
|
|
|
|
|
|
if (!exited && (exitcode = back->exitcode(backhandle)) >= 0)
|
|
|
|
[self endSession:(exitcode == 0)];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)endSession:(int)clean
|
|
|
|
{
|
|
|
|
exited = TRUE;
|
|
|
|
if (ldisc) {
|
|
|
|
ldisc_free(ldisc);
|
|
|
|
ldisc = NULL;
|
|
|
|
}
|
|
|
|
if (back) {
|
|
|
|
back->free(backhandle);
|
|
|
|
backhandle = NULL;
|
|
|
|
back = NULL;
|
|
|
|
//FIXME: update specials menu;
|
|
|
|
}
|
|
|
|
if (cfg.close_on_exit == FORCE_ON ||
|
|
|
|
(cfg.close_on_exit == AUTO && clean))
|
|
|
|
[self close];
|
|
|
|
// FIXME: else show restart menu item
|
|
|
|
}
|
|
|
|
|
2007-02-18 15:59:38 +00:00
|
|
|
- (Terminal *)term
|
|
|
|
{
|
|
|
|
return term;
|
|
|
|
}
|
|
|
|
|
2005-02-15 21:45:50 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
int from_backend(void *frontend, int is_stderr, const char *data, int len)
|
|
|
|
{
|
|
|
|
SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
return [win fromBackend:data len:len isStderr:is_stderr];
|
|
|
|
}
|
|
|
|
|
2007-02-18 15:59:38 +00:00
|
|
|
int from_backend_untrusted(void *frontend, const char *data, int len)
|
|
|
|
{
|
|
|
|
SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
return [win fromBackendUntrusted:data len:len];
|
|
|
|
}
|
|
|
|
|
2015-05-15 10:15:42 +00:00
|
|
|
int get_userpass_input(prompts_t *p, const unsigned char *in, int inlen)
|
2005-10-30 20:24:09 +00:00
|
|
|
{
|
|
|
|
SessionWindow *win = (SessionWindow *)p->frontend;
|
|
|
|
Terminal *term = [win term];
|
|
|
|
return term_get_userpass_input(term, p, in, inlen);
|
|
|
|
}
|
|
|
|
|
2005-02-15 21:45:50 +00:00
|
|
|
void frontend_keypress(void *handle)
|
|
|
|
{
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
void notify_remote_exit(void *frontend)
|
|
|
|
{
|
2005-02-26 13:37:07 +00:00
|
|
|
SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
|
|
|
|
[win notifyRemoteExit];
|
2005-02-15 21:45:50 +00:00
|
|
|
}
|
|
|
|
|
Move echo/edit state change functionality out of ldisc_send.
I'm not actually sure why we've always had back ends notify ldisc of
changes to echo/edit settings by giving ldisc_send(ldisc,NULL,0,0) a
special meaning, instead of by having a separate dedicated notify
function with its own prototype and parameter set. Coverity's recent
observation that the two kinds of call don't even have the same
requirements on the ldisc (particularly, whether ldisc->term can be
NULL) makes me realise that it's really high time I separated the two
conceptually different operations into actually different functions.
While I'm here, I've renamed the confusing ldisc_update() function
which that special operation ends up feeding to, because it's not
actually a function applying to an ldisc - it applies to a front end.
So ldisc_send(ldisc,NULL,0,0) is now ldisc_echoedit_update(ldisc), and
that in turn figures out the current echo/edit settings before passing
them on to frontend_echoedit_update(). I think that should be clearer.
2014-11-22 16:12:47 +00:00
|
|
|
void frontend_echoedit_update(void *frontend, int echo, int edit)
|
2005-02-15 21:45:50 +00:00
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/*
|
|
|
|
* In a GUI front end, this need do nothing.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2005-04-21 13:57:08 +00:00
|
|
|
char *get_ttymode(void *frontend, const char *mode)
|
|
|
|
{
|
2007-02-18 15:59:38 +00:00
|
|
|
SessionWindow *win = (SessionWindow *)frontend;
|
2005-04-21 13:57:08 +00:00
|
|
|
Terminal *term = [win term];
|
|
|
|
return term_get_ttymode(term, mode);
|
|
|
|
}
|
|
|
|
|
2005-02-15 21:45:50 +00:00
|
|
|
void update_specials_menu(void *frontend)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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).
|
|
|
|
*/
|
2005-12-09 20:04:19 +00:00
|
|
|
void do_beep(void *frontend, int mode)
|
2005-02-15 21:45:50 +00:00
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
if (mode != BELL_VISUAL)
|
|
|
|
NSBeep();
|
|
|
|
}
|
|
|
|
|
|
|
|
int char_width(Context ctx, int uc)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Under X, any fixed-width font really _is_ fixed-width.
|
|
|
|
* Double-width characters will be dealt with using a separate
|
|
|
|
* font. For the moment we can simply return 1.
|
|
|
|
*/
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void palette_set(void *frontend, int n, int r, int g, int b)
|
|
|
|
{
|
|
|
|
SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
|
|
|
|
if (n >= 16)
|
|
|
|
n += 256 - 16;
|
2013-07-22 07:12:26 +00:00
|
|
|
if (n >= NALLCOLOURS)
|
2005-02-15 21:45:50 +00:00
|
|
|
return;
|
|
|
|
[win setColour:n r:r/255.0 g:g/255.0 b:b/255.0];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: do we need an OS X equivalent of set_window_background?
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void palette_reset(void *frontend)
|
|
|
|
{
|
|
|
|
SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
Config *cfg = [win cfg];
|
|
|
|
|
|
|
|
/* This maps colour indices in cfg to those used in colours[]. */
|
|
|
|
static const int ww[] = {
|
|
|
|
256, 257, 258, 259, 260, 261,
|
|
|
|
0, 8, 1, 9, 2, 10, 3, 11,
|
|
|
|
4, 12, 5, 13, 6, 14, 7, 15
|
|
|
|
};
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < NCFGCOLOURS; i++) {
|
|
|
|
[win setColour:ww[i] r:cfg->colours[i][0]/255.0
|
|
|
|
g:cfg->colours[i][1]/255.0 b:cfg->colours[i][2]/255.0];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < NEXTCOLOURS; i++) {
|
|
|
|
if (i < 216) {
|
|
|
|
int r = i / 36, g = (i / 6) % 6, b = i % 6;
|
2005-10-13 21:56:43 +00:00
|
|
|
r = r ? r*40+55 : 0; g = g ? b*40+55 : 0; b = b ? b*40+55 : 0;
|
|
|
|
[win setColour:i+16 r:r/255.0 g:g/255.0 b:b/255.0];
|
2005-02-15 21:45:50 +00:00
|
|
|
} else {
|
|
|
|
int shade = i - 216;
|
2005-10-13 21:56:43 +00:00
|
|
|
float fshade = (shade * 10 + 8) / 255.0;
|
2005-02-15 21:45:50 +00:00
|
|
|
[win setColour:i+16 r:fshade g:fshade b:fshade];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: do we need an OS X equivalent of set_window_background?
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
Context get_ctx(void *frontend)
|
|
|
|
{
|
|
|
|
SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock the drawing focus on the image inside the TerminalView.
|
|
|
|
*/
|
|
|
|
[win drawStartFinish:YES];
|
|
|
|
|
|
|
|
[[NSGraphicsContext currentContext] setShouldAntialias:YES];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Cocoa drawing functions don't take a graphics context: that
|
|
|
|
* parameter is implicit. Therefore, we'll use the frontend
|
|
|
|
* handle itself as the context, on the grounds that it's as
|
|
|
|
* good a thing to use as any.
|
|
|
|
*/
|
|
|
|
return frontend;
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_ctx(Context ctx)
|
|
|
|
{
|
|
|
|
SessionWindow *win = (SessionWindow *)ctx;
|
|
|
|
|
|
|
|
[win drawStartFinish:NO];
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_text(Context ctx, int x, int y, wchar_t *text, int len,
|
|
|
|
unsigned long attr, int lattr)
|
|
|
|
{
|
|
|
|
SessionWindow *win = (SessionWindow *)ctx;
|
|
|
|
|
|
|
|
[win doText:text len:len x:x y:y attr:attr lattr:lattr];
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
|
|
|
|
unsigned long attr, int lattr)
|
|
|
|
{
|
|
|
|
SessionWindow *win = (SessionWindow *)ctx;
|
|
|
|
Config *cfg = [win cfg];
|
|
|
|
int active, passive;
|
|
|
|
|
|
|
|
if (attr & TATTR_PASCURS) {
|
|
|
|
attr &= ~TATTR_PASCURS;
|
|
|
|
passive = 1;
|
|
|
|
} else
|
|
|
|
passive = 0;
|
|
|
|
if ((attr & TATTR_ACTCURS) && cfg->cursor_type != 0) {
|
|
|
|
attr &= ~TATTR_ACTCURS;
|
|
|
|
active = 1;
|
|
|
|
} else
|
|
|
|
active = 0;
|
|
|
|
|
|
|
|
[win doText:text len:len x:x y:y attr:attr lattr:lattr];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: now draw the various cursor types (both passive and
|
|
|
|
* active underlines and vertical lines, plus passive blocks).
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Minimise or restore the window in response to a server-side
|
|
|
|
* request.
|
|
|
|
*/
|
|
|
|
void set_iconic(void *frontend, int iconic)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move the window in response to a server-side request.
|
|
|
|
*/
|
|
|
|
void move_window(void *frontend, int x, int y)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Refresh the window in response to a server-side request.
|
|
|
|
*/
|
|
|
|
void refresh_window(void *frontend)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Maximise or restore the window in response to a server-side
|
|
|
|
* request.
|
|
|
|
*/
|
|
|
|
void set_zoomed(void *frontend, int zoomed)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report whether the window is iconic, for terminal reports.
|
|
|
|
*/
|
|
|
|
int is_iconic(void *frontend)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
return NO; /* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report the window's position, for terminal reports.
|
|
|
|
*/
|
|
|
|
void get_window_pos(void *frontend, int *x, int *y)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report the window's pixel size, for terminal reports.
|
|
|
|
*/
|
|
|
|
void get_window_pixels(void *frontend, int *x, int *y)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the window or icon title.
|
|
|
|
*/
|
|
|
|
char *get_window_title(void *frontend, int icon)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
return NULL; /* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_title(void *frontend, char *title)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_icon(void *frontend, char *title)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_sbar(void *frontend, int total, int start, int page)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
void get_clip(void *frontend, wchar_t ** p, int *len)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
2006-02-14 13:14:08 +00:00
|
|
|
void write_clip(void *frontend, wchar_t *data, int *attr, int len, int must_deselect)
|
2005-02-15 21:45:50 +00:00
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
void request_paste(void *frontend)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_raw_mouse_mode(void *frontend, int activate)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
void request_resize(void *frontend, int w, int h)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
void sys_cursor(void *frontend, int x, int y)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/*
|
|
|
|
* This is probably meaningless under OS X. FIXME: find out for
|
|
|
|
* sure.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void logevent(void *frontend, const char *string)
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
/* FIXME */
|
|
|
|
printf("logevent: %s\n", string);
|
|
|
|
}
|
|
|
|
|
|
|
|
int font_dimension(void *frontend, int which)/* 0 for width, 1 for height */
|
|
|
|
{
|
|
|
|
//SessionWindow *win = (SessionWindow *)frontend;
|
|
|
|
return 1; /* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_busy_status(void *frontend, int status)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We need do nothing here: the OS X `application is busy'
|
|
|
|
* beachball pointer appears _automatically_ when the
|
|
|
|
* application isn't responding to GUI messages.
|
|
|
|
*/
|
|
|
|
}
|