mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 09:27:59 +00:00
Tentative merge of ben-mac-port (only dead for three years!) into the trunk.
This doesn't include any mkfiles.pl glue, and is missing one or two other fixes. The terminal emulator is kind of working, though, as, I believe, is the store module. Everything else is yet to be done. [originally from svn r2226]
This commit is contained in:
parent
b31bf55bc0
commit
c4eebb49a9
544
mac/mac.c
Normal file
544
mac/mac.c
Normal file
@ -0,0 +1,544 @@
|
||||
/* $Id: mac.c,v 1.1 2002/11/19 02:13:46 ben Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1999 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.
|
||||
*/
|
||||
/*
|
||||
* mac.c -- miscellaneous Mac-specific routines
|
||||
*/
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <Quickdraw.h>
|
||||
#include <Fonts.h>
|
||||
#include <MacWindows.h>
|
||||
#include <Menus.h>
|
||||
#include <TextEdit.h>
|
||||
#include <Appearance.h>
|
||||
#include <CodeFragments.h>
|
||||
#include <Dialogs.h>
|
||||
#include <Devices.h>
|
||||
#include <DiskInit.h>
|
||||
#include <Gestalt.h>
|
||||
#include <Resources.h>
|
||||
#include <Threads.h>
|
||||
#include <ToolUtils.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h> /* putty.h needs size_t */
|
||||
#include <stdio.h> /* for vsprintf */
|
||||
|
||||
#define PUTTY_DO_GLOBALS
|
||||
|
||||
#include "macresid.h"
|
||||
#include "putty.h"
|
||||
#include "mac.h"
|
||||
|
||||
QDGlobals qd;
|
||||
|
||||
static int cold = 1;
|
||||
struct mac_gestalts mac_gestalts;
|
||||
|
||||
static void mac_startup(void);
|
||||
static void mac_eventloop(void);
|
||||
#pragma noreturn (mac_eventloop)
|
||||
static void mac_event(EventRecord *);
|
||||
static void mac_contentclick(WindowPtr, EventRecord *);
|
||||
static void mac_growwindow(WindowPtr, EventRecord *);
|
||||
static void mac_activatewindow(WindowPtr, EventRecord *);
|
||||
static void mac_activateabout(WindowPtr, EventRecord *);
|
||||
static void mac_updatewindow(WindowPtr);
|
||||
static void mac_keypress(EventRecord *);
|
||||
static int mac_windowtype(WindowPtr);
|
||||
static void mac_menucommand(long);
|
||||
static void mac_openabout(void);
|
||||
static void mac_adjustcursor(RgnHandle);
|
||||
static void mac_adjustmenus(void);
|
||||
static void mac_closewindow(WindowPtr);
|
||||
static void mac_zoomwindow(WindowPtr, short);
|
||||
static void mac_shutdown(void);
|
||||
#pragma noreturn (mac_shutdown)
|
||||
|
||||
struct mac_windows {
|
||||
WindowPtr about;
|
||||
WindowPtr licence;
|
||||
};
|
||||
|
||||
struct mac_windows windows;
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
|
||||
mac_startup();
|
||||
mac_eventloop();
|
||||
}
|
||||
|
||||
#pragma noreturn (main)
|
||||
|
||||
static void mac_startup(void) {
|
||||
Handle menuBar;
|
||||
|
||||
/* Init Memory Manager */
|
||||
MaxApplZone();
|
||||
/* Init QuickDraw */
|
||||
InitGraf(&qd.thePort);
|
||||
/* Init Font Manager */
|
||||
InitFonts();
|
||||
/* Init Window Manager */
|
||||
InitWindows();
|
||||
/* Init Menu Manager */
|
||||
InitMenus();
|
||||
/* Init TextEdit */
|
||||
TEInit();
|
||||
/* Init Dialog Manager */
|
||||
InitDialogs(nil);
|
||||
cold = 0;
|
||||
|
||||
/* Check for the Thread Manager. Bail out if it's not there. */
|
||||
if (Gestalt(gestaltThreadMgrAttr, &mac_gestalts.thdsattr) != noErr ||
|
||||
!(mac_gestalts.thdsattr & (1 << gestaltThreadMgrPresent)) ||
|
||||
&NewThread == kUnresolvedCFragSymbolAddress)
|
||||
fatalbox("PuTTY requires the Thread Manager in order to operate. "
|
||||
"The Thread Manager can be obtained from Apple Software "
|
||||
"Updates.");
|
||||
/* Find out if we've got Color Quickdraw */
|
||||
if (Gestalt(gestaltQuickdrawVersion, &mac_gestalts.qdvers) != noErr)
|
||||
mac_gestalts.qdvers = gestaltOriginalQD;
|
||||
/* ... and the Appearance Manager? */
|
||||
if (Gestalt(gestaltAppearanceVersion, &mac_gestalts.apprvers) != noErr)
|
||||
if (Gestalt(gestaltAppearanceAttr, NULL) == noErr)
|
||||
mac_gestalts.apprvers = 0x0100;
|
||||
else
|
||||
mac_gestalts.apprvers = 0;
|
||||
#if TARGET_RT_MAC_CFM
|
||||
/* Paranoia: Did we manage to pull in AppearanceLib? */
|
||||
if (&RegisterAppearanceClient == kUnresolvedCFragSymbolAddress)
|
||||
mac_gestalts.apprvers = 0;
|
||||
#endif
|
||||
/* Mac OS 8.5 Control Manager (proportional scrollbars)? */
|
||||
if (Gestalt(gestaltControlMgrAttr, &mac_gestalts.cntlattr) != noErr)
|
||||
mac_gestalts.cntlattr = 0;
|
||||
/* Mac OS 8.5 Window Manager? */
|
||||
if (Gestalt(gestaltWindowMgrAttr, &mac_gestalts.windattr) != noErr)
|
||||
mac_gestalts.windattr = 0;
|
||||
|
||||
/* We've been tested with the Appearance Manager */
|
||||
if (mac_gestalts.apprvers != 0)
|
||||
RegisterAppearanceClient();
|
||||
|
||||
menuBar = GetNewMBar(128);
|
||||
if (menuBar == NULL)
|
||||
fatalbox("Unable to create menu bar.");
|
||||
SetMenuBar(menuBar);
|
||||
AppendResMenu(GetMenuHandle(mApple), 'DRVR');
|
||||
mac_adjustmenus();
|
||||
DrawMenuBar();
|
||||
InitCursor();
|
||||
windows.about = NULL;
|
||||
windows.licence = NULL;
|
||||
|
||||
init_ucs();
|
||||
}
|
||||
|
||||
static void mac_eventloop(void) {
|
||||
Boolean gotevent;
|
||||
EventRecord event;
|
||||
RgnHandle cursrgn;
|
||||
|
||||
cursrgn = NewRgn();
|
||||
for (;;) {
|
||||
mac_adjustcursor(cursrgn);
|
||||
gotevent = WaitNextEvent(everyEvent, &event, LONG_MAX, cursrgn);
|
||||
mac_adjustcursor(cursrgn);
|
||||
if (gotevent)
|
||||
mac_event(&event);
|
||||
YieldToAnyThread();
|
||||
}
|
||||
DisposeRgn(cursrgn);
|
||||
}
|
||||
|
||||
static void mac_event(EventRecord *event) {
|
||||
short part;
|
||||
WindowPtr window;
|
||||
Point pt;
|
||||
|
||||
switch (event->what) {
|
||||
case mouseDown:
|
||||
part = FindWindow(event->where, &window);
|
||||
switch (part) {
|
||||
case inMenuBar:
|
||||
mac_adjustmenus();
|
||||
mac_menucommand(MenuSelect(event->where));
|
||||
break;
|
||||
case inSysWindow:
|
||||
SystemClick(event, window);
|
||||
break;
|
||||
case inContent:
|
||||
if (window != FrontWindow())
|
||||
/* XXX: check for movable modal dboxes? */
|
||||
SelectWindow(window);
|
||||
else
|
||||
mac_contentclick(window, event);
|
||||
break;
|
||||
case inGoAway:
|
||||
if (TrackGoAway(window, event->where))
|
||||
mac_closewindow(window);
|
||||
break;
|
||||
case inDrag:
|
||||
/* XXX: moveable modal check? */
|
||||
DragWindow(window, event->where, &qd.screenBits.bounds);
|
||||
break;
|
||||
case inGrow:
|
||||
mac_growwindow(window, event);
|
||||
break;
|
||||
case inZoomIn:
|
||||
case inZoomOut:
|
||||
if (TrackBox(window, event->where, part))
|
||||
mac_zoomwindow(window, part);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case keyDown:
|
||||
case autoKey:
|
||||
mac_keypress(event);
|
||||
break;
|
||||
case activateEvt:
|
||||
mac_activatewindow((WindowPtr)event->message, event);
|
||||
break;
|
||||
case updateEvt:
|
||||
mac_updatewindow((WindowPtr)event->message);
|
||||
break;
|
||||
case diskEvt:
|
||||
if (HiWord(event->message) != noErr) {
|
||||
SetPt(&pt, 120, 120);
|
||||
DIBadMount(pt, event->message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mac_contentclick(WindowPtr window, EventRecord *event) {
|
||||
short item;
|
||||
|
||||
switch (mac_windowtype(window)) {
|
||||
case wTerminal:
|
||||
mac_clickterm(window, event);
|
||||
break;
|
||||
case wAbout:
|
||||
if (DialogSelect(event, &(DialogPtr)window, &item))
|
||||
switch (item) {
|
||||
case wiAboutLicence:
|
||||
/* XXX: Do something */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mac_growwindow(WindowPtr window, EventRecord *event) {
|
||||
|
||||
switch (mac_windowtype(window)) {
|
||||
case wTerminal:
|
||||
mac_growterm(window, event);
|
||||
}
|
||||
}
|
||||
|
||||
static void mac_activatewindow(WindowPtr window, EventRecord *event) {
|
||||
int active;
|
||||
|
||||
active = (event->modifiers & activeFlag) != 0;
|
||||
mac_adjustmenus();
|
||||
switch (mac_windowtype(window)) {
|
||||
case wTerminal:
|
||||
mac_activateterm(window, active);
|
||||
break;
|
||||
case wAbout:
|
||||
mac_activateabout(window, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mac_activateabout(WindowPtr window, EventRecord *event) {
|
||||
DialogItemType itemtype;
|
||||
Handle itemhandle;
|
||||
short item;
|
||||
Rect itemrect;
|
||||
int active;
|
||||
|
||||
active = (event->modifiers & activeFlag) != 0;
|
||||
GetDialogItem(window, wiAboutLicence, &itemtype, &itemhandle, &itemrect);
|
||||
HiliteControl((ControlHandle)itemhandle, active ? 0 : 255);
|
||||
DialogSelect(event, &window, &item);
|
||||
}
|
||||
|
||||
static void mac_updatewindow(WindowPtr window) {
|
||||
|
||||
switch (mac_windowtype(window)) {
|
||||
case wTerminal:
|
||||
mac_updateterm(window);
|
||||
break;
|
||||
case wAbout:
|
||||
BeginUpdate(window);
|
||||
UpdateDialog(window, window->visRgn);
|
||||
EndUpdate(window);
|
||||
break;
|
||||
case wLicence:
|
||||
/* Do something */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Work out what kind of window we're dealing with.
|
||||
* Concept shamelessly nicked from SurfWriter.
|
||||
*/
|
||||
static int mac_windowtype(WindowPtr window) {
|
||||
int kind;
|
||||
|
||||
if (window == NULL)
|
||||
return wNone;
|
||||
kind = ((WindowPeek)window)->windowKind;
|
||||
if (kind < 0)
|
||||
return wDA;
|
||||
if (GetWVariant(window) == zoomDocProc)
|
||||
return wTerminal;
|
||||
return GetWRefCon(window);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a key press
|
||||
*/
|
||||
static void mac_keypress(EventRecord *event) {
|
||||
WindowPtr window;
|
||||
|
||||
window = FrontWindow();
|
||||
/*
|
||||
* Check for a command-key combination, but ignore it if it counts
|
||||
* as a meta-key combination and we're in a terminal window.
|
||||
*/
|
||||
if (event->what == keyDown && (event->modifiers & cmdKey) /*&&
|
||||
!((event->modifiers & cfg.meta_modifiers) == cfg.meta_modifiers &&
|
||||
mac_windowtype(window) == wTerminal)*/) {
|
||||
mac_adjustmenus();
|
||||
mac_menucommand(MenuKey(event->message & charCodeMask));
|
||||
} else {
|
||||
switch (mac_windowtype(window)) {
|
||||
case wTerminal:
|
||||
mac_keyterm(window, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mac_menucommand(long result) {
|
||||
short menu, item;
|
||||
Str255 da;
|
||||
WindowPtr window;
|
||||
|
||||
menu = HiWord(result);
|
||||
item = LoWord(result);
|
||||
window = FrontWindow();
|
||||
/* Things which do the same whatever window we're in. */
|
||||
switch (menu) {
|
||||
case mApple:
|
||||
switch (item) {
|
||||
case iAbout:
|
||||
mac_openabout();
|
||||
goto done;
|
||||
default:
|
||||
GetMenuItemText(GetMenuHandle(mApple), item, da);
|
||||
OpenDeskAcc(da);
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case mFile:
|
||||
switch (item) {
|
||||
case iNew:
|
||||
mac_newsession();
|
||||
goto done;
|
||||
case iClose:
|
||||
mac_closewindow(window);
|
||||
goto done;
|
||||
case iQuit:
|
||||
mac_shutdown();
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* If we get here, handling is up to window-specific code. */
|
||||
switch (mac_windowtype(window)) {
|
||||
case wTerminal:
|
||||
mac_menuterm(window, menu, item);
|
||||
break;
|
||||
}
|
||||
done:
|
||||
HiliteMenu(0);
|
||||
}
|
||||
|
||||
static void mac_openabout(void) {
|
||||
DialogItemType itemtype;
|
||||
Handle item;
|
||||
VersRecHndl vers;
|
||||
Rect box;
|
||||
StringPtr longvers;
|
||||
|
||||
if (windows.about)
|
||||
SelectWindow(windows.about);
|
||||
else {
|
||||
windows.about = GetNewDialog(wAbout, NULL, (WindowPtr)-1);
|
||||
/* XXX check we're using the right resource file? */
|
||||
vers = (VersRecHndl)GetResource('vers', 1);
|
||||
assert(vers != NULL && *vers != NULL);
|
||||
longvers = (*vers)->shortVersion + (*vers)->shortVersion[0] + 1;
|
||||
GetDialogItem(windows.about, wiAboutVersion, &itemtype, &item, &box);
|
||||
assert(itemtype & kStaticTextDialogItem);
|
||||
SetDialogItemText(item, longvers);
|
||||
ShowWindow(windows.about);
|
||||
}
|
||||
}
|
||||
|
||||
static void mac_closewindow(WindowPtr window) {
|
||||
|
||||
switch (mac_windowtype(window)) {
|
||||
case wDA:
|
||||
CloseDeskAcc(((WindowPeek)window)->windowKind);
|
||||
break;
|
||||
case wTerminal:
|
||||
/* FIXME: end session and stuff */
|
||||
break;
|
||||
case wAbout:
|
||||
windows.about = NULL;
|
||||
CloseWindow(window);
|
||||
break;
|
||||
default:
|
||||
CloseWindow(window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mac_zoomwindow(WindowPtr window, short part) {
|
||||
|
||||
/* FIXME: do something */
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the menus look right before the user gets to see them.
|
||||
*/
|
||||
static void mac_adjustmenus(void) {
|
||||
WindowPtr window;
|
||||
MenuHandle menu;
|
||||
|
||||
window = FrontWindow();
|
||||
menu = GetMenuHandle(mApple);
|
||||
EnableItem(menu, 0);
|
||||
EnableItem(menu, iAbout);
|
||||
|
||||
menu = GetMenuHandle(mFile);
|
||||
EnableItem(menu, 0);
|
||||
EnableItem(menu, iNew);
|
||||
if (window != NULL)
|
||||
EnableItem(menu, iClose);
|
||||
else
|
||||
DisableItem(menu, iClose);
|
||||
EnableItem(menu, iQuit);
|
||||
|
||||
switch (mac_windowtype(window)) {
|
||||
case wTerminal:
|
||||
mac_adjusttermmenus(window);
|
||||
break;
|
||||
default:
|
||||
menu = GetMenuHandle(mEdit);
|
||||
DisableItem(menu, 0);
|
||||
break;
|
||||
}
|
||||
DrawMenuBar();
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the right cursor's being displayed.
|
||||
*/
|
||||
static void mac_adjustcursor(RgnHandle cursrgn) {
|
||||
Point mouse;
|
||||
WindowPtr window, front;
|
||||
short part;
|
||||
|
||||
GetMouse(&mouse);
|
||||
LocalToGlobal(&mouse);
|
||||
part = FindWindow(mouse, &window);
|
||||
front = FrontWindow();
|
||||
if (part != inContent || window == NULL || window != front) {
|
||||
/* Cursor isn't in the front window, so switch to arrow */
|
||||
SetCursor(&qd.arrow);
|
||||
SetRectRgn(cursrgn, SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX);
|
||||
if (front != NULL)
|
||||
DiffRgn(cursrgn, front->visRgn, cursrgn);
|
||||
} else {
|
||||
switch (mac_windowtype(window)) {
|
||||
case wTerminal:
|
||||
mac_adjusttermcursor(window, mouse, cursrgn);
|
||||
break;
|
||||
default:
|
||||
SetCursor(&qd.arrow);
|
||||
CopyRgn(window->visRgn, cursrgn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mac_shutdown(void) {
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void fatalbox(char *fmt, ...) {
|
||||
va_list ap;
|
||||
Str255 stuff;
|
||||
|
||||
va_start(ap, fmt);
|
||||
/* We'd like stuff to be a Pascal string */
|
||||
stuff[0] = vsprintf((char *)(&stuff[1]), fmt, ap);
|
||||
va_end(ap);
|
||||
ParamText(stuff, NULL, NULL, NULL);
|
||||
StopAlert(128, nil);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void modalfatalbox(char *fmt, ...) {
|
||||
va_list ap;
|
||||
Str255 stuff;
|
||||
|
||||
va_start(ap, fmt);
|
||||
/* We'd like stuff to be a Pascal string */
|
||||
stuff[0] = vsprintf((char *)(&stuff[1]), fmt, ap);
|
||||
va_end(ap);
|
||||
ParamText(stuff, NULL, NULL, NULL);
|
||||
StopAlert(128, nil);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* c-file-style: "simon"
|
||||
* End:
|
||||
*/
|
79
mac/mac.h
Normal file
79
mac/mac.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* mac.h -- macintosh-specific declarations
|
||||
*/
|
||||
|
||||
#ifndef PUTTY_MAC_H
|
||||
#define PUTTY_MAC_H
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <Events.h>
|
||||
#include <Gestalt.h>
|
||||
#include <MacWindows.h>
|
||||
#include <Palettes.h>
|
||||
|
||||
struct mac_gestalts {
|
||||
long qdvers;
|
||||
long apprvers;
|
||||
long cntlattr;
|
||||
long windattr;
|
||||
long thdsattr;
|
||||
};
|
||||
|
||||
extern struct mac_gestalts mac_gestalts;
|
||||
|
||||
#define HAVE_COLOR_QD() (mac_gestalts.qdvers > gestaltOriginalQD)
|
||||
|
||||
/* from macterm.c */
|
||||
extern void mac_newsession(void);
|
||||
extern void mac_activateterm(WindowPtr, Boolean);
|
||||
extern void mac_adjusttermcursor(WindowPtr, Point, RgnHandle);
|
||||
extern void mac_adjusttermmenus(WindowPtr);
|
||||
extern void mac_updateterm(WindowPtr);
|
||||
extern void mac_clickterm(WindowPtr, EventRecord *);
|
||||
extern void mac_growterm(WindowPtr, EventRecord *);
|
||||
extern void mac_keyterm(WindowPtr, EventRecord *);
|
||||
extern void mac_menuterm(WindowPtr, short, short);
|
||||
/* from maccfg.c */
|
||||
extern void mac_loadconfig(Config *);
|
||||
/* from macnet.c */
|
||||
extern void macnet_eventcheck(void);
|
||||
|
||||
typedef struct {
|
||||
/* Config that created this session */
|
||||
Config cfg;
|
||||
/* Terminal emulator internal state */
|
||||
Terminal *term;
|
||||
/* Display state */
|
||||
int font_width, font_height;
|
||||
int has_focus;
|
||||
/* Line discipline */
|
||||
void *ldisc;
|
||||
/* Backend */
|
||||
Backend *back;
|
||||
void *backhandle;
|
||||
char *realhost;
|
||||
/* Logging */
|
||||
void *logctx;
|
||||
/* Conveniences */
|
||||
unsigned long attr_mask; /* Mask of attributes to display */
|
||||
|
||||
/* Mac-specific elements */
|
||||
short fontnum;
|
||||
int font_ascent;
|
||||
int font_leading;
|
||||
int font_boldadjust;
|
||||
WindowPtr window;
|
||||
PaletteHandle palette;
|
||||
ControlHandle scrollbar;
|
||||
WCTabHandle wctab;
|
||||
ThreadID thread;
|
||||
int raw_mouse;
|
||||
} Session;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* c-file-style: "simon"
|
||||
* End:
|
||||
*/
|
49
mac/macresid.h
Normal file
49
mac/macresid.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* $Id: macresid.h,v 1.1 2002/11/19 02:13:46 ben Exp $ */
|
||||
|
||||
/*
|
||||
* macresid.h -- Mac resource IDs
|
||||
*
|
||||
* This file is shared by C and Rez source files
|
||||
*/
|
||||
|
||||
|
||||
/* Menu bar IDs */
|
||||
#define MBAR_Main 128
|
||||
|
||||
/* Menu IDs */
|
||||
#define mApple 128
|
||||
#define mFile 129
|
||||
#define mEdit 130
|
||||
|
||||
/* Menu Items */
|
||||
/* Apple menu */
|
||||
#define iAbout 1
|
||||
/* File menu */
|
||||
#define iNew 1
|
||||
#define iClose 2
|
||||
#define iQuit 4
|
||||
/* Edit menu */
|
||||
#define iUndo 1
|
||||
#define iCut 3
|
||||
#define iCopy 4
|
||||
#define iPaste 5
|
||||
#define iClear 6
|
||||
#define iSelectAll 7
|
||||
|
||||
/* Window types (and resource IDs) */
|
||||
#define wNone 0 /* Dummy value for no window */
|
||||
#define wDA 1 /* Dummy value for desk accessory */
|
||||
#define wFatal 128
|
||||
#define wAbout 129
|
||||
#define wiAboutLicence 1
|
||||
#define wiAboutVersion 3
|
||||
#define wTerminal 130
|
||||
#define wLicence 131
|
||||
|
||||
/* Controls */
|
||||
#define cVScroll 128
|
||||
|
||||
/* Preferences */
|
||||
#define PREF_wordness_type 'wORD'
|
||||
|
||||
#define PREF_settings 1024
|
348
mac/macstore.c
Normal file
348
mac/macstore.c
Normal file
@ -0,0 +1,348 @@
|
||||
/* $Id: macstore.c,v 1.1 2002/11/19 02:13:46 ben Exp $ */
|
||||
|
||||
/*
|
||||
* macstore.c: Macintosh-specific impementation of the interface
|
||||
* defined in storage.h
|
||||
*/
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <Folders.h>
|
||||
#include <Memory.h>
|
||||
#include <Resources.h>
|
||||
#include <TextUtils.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "putty.h"
|
||||
#include "storage.h"
|
||||
|
||||
#define PUTTY_CREATOR FOUR_CHAR_CODE('pTTY')
|
||||
#define SESS_TYPE FOUR_CHAR_CODE('Sess')
|
||||
|
||||
|
||||
OSErr get_session_dir(Boolean makeit, short *pVRefNum, long *pDirID);
|
||||
OSErr FSpGetDirID(FSSpec *f, long *idp, Boolean makeit);
|
||||
|
||||
/*
|
||||
* We store each session as a file in the "PuTTY" sub-directory of the
|
||||
* preferences folder. Each (key,value) pair is stored as a resource.
|
||||
*/
|
||||
|
||||
OSErr get_session_dir(Boolean makeit, short *pVRefNum, long *pDirID) {
|
||||
OSErr error = noErr;
|
||||
short prefVRefNum;
|
||||
FSSpec puttydir, sessdir;
|
||||
long prefDirID, puttyDirID, sessDirID;
|
||||
|
||||
error = FindFolder(kOnSystemDisk, kPreferencesFolderType, makeit,
|
||||
&prefVRefNum, &prefDirID);
|
||||
if (error != noErr) goto out;
|
||||
|
||||
error = FSMakeFSSpec(prefVRefNum, prefDirID, "\pPuTTY", &puttydir);
|
||||
if (error != noErr && error != fnfErr) goto out;
|
||||
error = FSpGetDirID(&puttydir, &puttyDirID, makeit);
|
||||
if (error != noErr) goto out;
|
||||
|
||||
error = FSMakeFSSpec(prefVRefNum, puttyDirID, "\pSaved Sessions",
|
||||
&sessdir);
|
||||
if (error != noErr && error != fnfErr) goto out;
|
||||
error = FSpGetDirID(&sessdir, &sessDirID, makeit);
|
||||
if (error != noErr) goto out;
|
||||
|
||||
*pVRefNum = prefVRefNum;
|
||||
*pDirID = sessDirID;
|
||||
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
OSErr FSpGetDirID(FSSpec *f, long *idp, Boolean makeit) {
|
||||
CInfoPBRec pb;
|
||||
OSErr error = noErr;
|
||||
|
||||
pb.dirInfo.ioNamePtr = f->name;
|
||||
pb.dirInfo.ioVRefNum = f->vRefNum;
|
||||
pb.dirInfo.ioDrDirID = f->parID;
|
||||
pb.dirInfo.ioFDirIndex = 0;
|
||||
error = PBGetCatInfoSync(&pb);
|
||||
if (error == fnfErr && makeit)
|
||||
return FSpDirCreate(f, smSystemScript, idp);
|
||||
if (error != noErr) goto out;
|
||||
if ((pb.dirInfo.ioFlAttrib & ioDirMask) == 0) {
|
||||
error = dirNFErr;
|
||||
goto out;
|
||||
}
|
||||
*idp = pb.dirInfo.ioDrDirID;
|
||||
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
struct write_settings {
|
||||
int fd;
|
||||
FSSpec tmpfile;
|
||||
FSSpec dstfile;
|
||||
};
|
||||
|
||||
void *open_settings_w(char *sessionname) {
|
||||
short sessVRefNum, tmpVRefNum;
|
||||
long sessDirID, tmpDirID;
|
||||
FSSpec sessfile;
|
||||
OSErr error;
|
||||
Str255 psessionname;
|
||||
struct write_settings *ws;
|
||||
|
||||
ws = safemalloc(sizeof *ws);
|
||||
error = get_session_dir(kCreateFolder, &sessVRefNum, &sessDirID);
|
||||
if (error != noErr) goto out;
|
||||
|
||||
c2pstrcpy(psessionname, sessionname);
|
||||
error = FSMakeFSSpec(sessVRefNum, sessDirID, psessionname, &ws->dstfile);
|
||||
if (error != noErr && error != fnfErr) goto out;
|
||||
if (error == fnfErr) {
|
||||
FSpCreateResFile(&ws->dstfile, PUTTY_CREATOR, SESS_TYPE,
|
||||
smSystemScript);
|
||||
if ((error = ResError()) != noErr) goto out;
|
||||
}
|
||||
|
||||
/* Create a temporary file to save to first. */
|
||||
error = FindFolder(sessVRefNum, kTemporaryFolderType, kCreateFolder,
|
||||
&tmpVRefNum, &tmpDirID);
|
||||
if (error != noErr) goto out;
|
||||
error = FSMakeFSSpec(tmpVRefNum, tmpDirID, psessionname, &ws->tmpfile);
|
||||
if (error != noErr && error != fnfErr) goto out;
|
||||
if (error == noErr) {
|
||||
error = FSpDelete(&ws->tmpfile);
|
||||
if (error != noErr) goto out;
|
||||
}
|
||||
FSpCreateResFile(&ws->tmpfile, PUTTY_CREATOR, SESS_TYPE, smSystemScript);
|
||||
if ((error = ResError()) != noErr) goto out;
|
||||
|
||||
ws->fd = FSpOpenResFile(&ws->tmpfile, fsWrPerm);
|
||||
if (ws->fd == -1) {error = ResError(); goto out;}
|
||||
|
||||
return ws;
|
||||
|
||||
out:
|
||||
safefree(ws);
|
||||
fatalbox("Failed to open session for write (%d)", error);
|
||||
}
|
||||
|
||||
void write_setting_s(void *handle, char *key, char *value) {
|
||||
int fd = *(int *)handle;
|
||||
Handle h;
|
||||
int id;
|
||||
OSErr error;
|
||||
|
||||
UseResFile(fd);
|
||||
if (ResError() != noErr)
|
||||
fatalbox("Failed to open saved session (%d)", ResError());
|
||||
|
||||
error = PtrToHand(value, &h, strlen(value));
|
||||
if (error != noErr)
|
||||
fatalbox("Failed to allocate memory");
|
||||
/* Put the data in a resource. */
|
||||
id = Unique1ID(FOUR_CHAR_CODE('TEXT'));
|
||||
if (ResError() != noErr)
|
||||
fatalbox("Failed to get ID for resource %s (%d)", key, ResError());
|
||||
addresource(h, FOUR_CHAR_CODE('TEXT'), id, key);
|
||||
if (ResError() != noErr)
|
||||
fatalbox("Failed to add resource %s (%d)", key, ResError());
|
||||
}
|
||||
|
||||
void write_setting_i(void *handle, char *key, int value) {
|
||||
int fd = *(int *)handle;
|
||||
Handle h;
|
||||
int id;
|
||||
OSErr error;
|
||||
|
||||
UseResFile(fd);
|
||||
if (ResError() != noErr)
|
||||
fatalbox("Failed to open saved session (%d)", ResError());
|
||||
|
||||
/* XXX assume all systems have the same "int" format */
|
||||
error = PtrToHand(&value, &h, sizeof(int));
|
||||
if (error != noErr)
|
||||
fatalbox("Failed to allocate memory (%d)", error);
|
||||
|
||||
/* Put the data in a resource. */
|
||||
id = Unique1ID(FOUR_CHAR_CODE('Int '));
|
||||
if (ResError() != noErr)
|
||||
fatalbox("Failed to get ID for resource %s (%d)", key, ResError());
|
||||
addresource(h, FOUR_CHAR_CODE('Int '), id, key);
|
||||
if (ResError() != noErr)
|
||||
fatalbox("Failed to add resource %s (%d)", key, ResError());
|
||||
}
|
||||
|
||||
void close_settings_w(void *handle) {
|
||||
struct write_settings *ws = handle;
|
||||
OSErr error;
|
||||
|
||||
CloseResFile(ws->fd);
|
||||
if ((error = ResError()) != noErr)
|
||||
goto out;
|
||||
error = FSpExchangeFiles(&ws->tmpfile, &ws->dstfile);
|
||||
if (error != noErr) goto out;
|
||||
error = FSpDelete(&ws->tmpfile);
|
||||
if (error != noErr) goto out;
|
||||
return;
|
||||
|
||||
out:
|
||||
fatalbox("Close of saved session failed (%d)", error);
|
||||
safefree(handle);
|
||||
}
|
||||
|
||||
void *open_settings_r(char *sessionname) {
|
||||
short sessVRefNum;
|
||||
long sessDirID;
|
||||
FSSpec sessfile;
|
||||
OSErr error;
|
||||
Str255 psessionname;
|
||||
int fd;
|
||||
int *handle;
|
||||
|
||||
error = get_session_dir(kDontCreateFolder, &sessVRefNum, &sessDirID);
|
||||
|
||||
c2pstrcpy(psessionname, sessionname);
|
||||
error = FSMakeFSSpec(sessVRefNum, sessDirID, psessionname, &sessfile);
|
||||
if (error != noErr) goto out;
|
||||
fd = FSpOpenResFile(&sessfile, fsRdPerm);
|
||||
if (fd == 0) {error = ResError(); goto out;}
|
||||
|
||||
handle = safemalloc(sizeof *handle);
|
||||
*handle = fd;
|
||||
return handle;
|
||||
|
||||
out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *read_setting_s(void *handle, char *key, char *buffer, int buflen) {
|
||||
int fd;
|
||||
Handle h;
|
||||
OSErr error;
|
||||
|
||||
if (handle == NULL) goto out;
|
||||
fd = *(int *)handle;
|
||||
UseResFile(fd);
|
||||
if (ResError() != noErr) goto out;
|
||||
h = get1namedresource(FOUR_CHAR_CODE('TEXT'), key);
|
||||
if (h == NULL) goto out;
|
||||
|
||||
if (GetHandleSize(h) > buflen) goto out;
|
||||
p2cstrcpy(buffer, (StringPtr)*h);
|
||||
ReleaseResource(h);
|
||||
if (ResError() != noErr) goto out;
|
||||
return buffer;
|
||||
|
||||
out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int read_setting_i(void *handle, char *key, int defvalue) {
|
||||
int fd;
|
||||
Handle h;
|
||||
OSErr error;
|
||||
int value;
|
||||
|
||||
if (handle == NULL) goto out;
|
||||
fd = *(int *)handle;
|
||||
UseResFile(fd);
|
||||
if (ResError() != noErr) goto out;
|
||||
h = get1namedresource(FOUR_CHAR_CODE('Int '), key);
|
||||
if (h == NULL) goto out;
|
||||
value = *(int *)*h;
|
||||
ReleaseResource(h);
|
||||
if (ResError() != noErr) goto out;
|
||||
return value;
|
||||
|
||||
out:
|
||||
return defvalue;
|
||||
}
|
||||
|
||||
void close_settings_r(void *handle) {
|
||||
int fd;
|
||||
|
||||
if (handle == NULL) return;
|
||||
fd = *(int *)handle;
|
||||
CloseResFile(fd);
|
||||
if (ResError() != noErr)
|
||||
fatalbox("Close of saved session failed (%d)", ResError());
|
||||
safefree(handle);
|
||||
}
|
||||
|
||||
void del_settings(char *sessionname) {
|
||||
OSErr error;
|
||||
FSSpec sessfile;
|
||||
short sessVRefNum;
|
||||
long sessDirID;
|
||||
Str255 psessionname;
|
||||
|
||||
error = get_session_dir(kDontCreateFolder, &sessVRefNum, &sessDirID);
|
||||
|
||||
c2pstrcpy(psessionname, sessionname);
|
||||
error = FSMakeFSSpec(sessVRefNum, sessDirID, psessionname, &sessfile);
|
||||
if (error != noErr) goto out;
|
||||
|
||||
error = FSpDelete(&sessfile);
|
||||
return;
|
||||
out:
|
||||
fatalbox("Delete session failed (%d)", error);
|
||||
}
|
||||
|
||||
struct enum_settings_state {
|
||||
short vRefNum;
|
||||
long dirID;
|
||||
int index;
|
||||
};
|
||||
|
||||
void *enum_settings_start(void) {
|
||||
OSErr error;
|
||||
struct enum_settings_state *state;
|
||||
|
||||
state = safemalloc(sizeof(*state));
|
||||
error = get_session_dir(kDontCreateFolder, &state->vRefNum, &state->dirID);
|
||||
if (error != noErr) {
|
||||
safefree(state);
|
||||
return NULL;
|
||||
}
|
||||
state->index = 1;
|
||||
return state;
|
||||
}
|
||||
|
||||
char *enum_settings_next(void *handle, char *buffer, int buflen) {
|
||||
struct enum_settings_state *e = handle;
|
||||
CInfoPBRec pb;
|
||||
OSErr error = noErr;
|
||||
Str255 name;
|
||||
|
||||
if (e == NULL) return NULL;
|
||||
do {
|
||||
pb.hFileInfo.ioNamePtr = name;
|
||||
pb.hFileInfo.ioVRefNum = e->vRefNum;
|
||||
pb.hFileInfo.ioDirID = e->dirID;
|
||||
pb.hFileInfo.ioFDirIndex = e->index++;
|
||||
error = PBGetCatInfoSync(&pb);
|
||||
if (error != noErr) return NULL;
|
||||
} while (!((pb.hFileInfo.ioFlAttrib & ioDirMask) == 0 &&
|
||||
pb.hFileInfo.ioFlFndrInfo.fdCreator == PUTTY_CREATOR &&
|
||||
pb.hFileInfo.ioFlFndrInfo.fdType == SESS_TYPE &&
|
||||
name[0] < buflen));
|
||||
|
||||
p2cstrcpy(buffer, name);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void enum_settings_finish(void *handle) {
|
||||
|
||||
safefree(handle);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Emacs magic:
|
||||
* Local Variables:
|
||||
* c-file-style: "simon"
|
||||
* End:
|
||||
*/
|
29
mac/macstuff.h
Normal file
29
mac/macstuff.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* macstuff.h -- Mac-specific definitions visible to the rest of PuTTY.
|
||||
*/
|
||||
|
||||
typedef void *Context; /* FIXME */
|
||||
|
||||
/*
|
||||
* On the Mac, Unicode text copied to the clipboard has U+2028 line separators.
|
||||
* Non-Unicode text will have these converted to CR along with the rest of the
|
||||
* content.
|
||||
*/
|
||||
#define SEL_NL { 0x2028 }
|
||||
|
||||
|
||||
#include <Events.h> /* Timing related goo */
|
||||
|
||||
#define GETTICKCOUNT TickCount
|
||||
#define CURSORBLINK GetCaretTime()
|
||||
#define TICKSPERSEC 60
|
||||
|
||||
#define DEFAULT_CODEPAGE 0 /* FIXME: no idea how to do this */
|
||||
|
||||
#define WCHAR wchar_t
|
||||
#define BYTE unsigned char
|
||||
|
||||
/* To make it compile */
|
||||
|
||||
#include <stdarg.h>
|
||||
extern int vsnprintf(char *, size_t, char const *, va_list);
|
1353
mac/macterm.c
Normal file
1353
mac/macterm.c
Normal file
File diff suppressed because it is too large
Load Diff
76
mac/macucs.c
Normal file
76
mac/macucs.c
Normal file
@ -0,0 +1,76 @@
|
||||
/* $Id: macucs.c,v 1.1 2002/11/19 02:13:46 ben Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <time.h>
|
||||
#include "putty.h"
|
||||
#include "terminal.h"
|
||||
#include "misc.h"
|
||||
|
||||
/*
|
||||
* Mac Unicode-handling routines.
|
||||
*
|
||||
* FIXME: currently trivial stub versions assuming all codepages
|
||||
* are ISO8859-1.
|
||||
*
|
||||
* What we _should_ do is to use the Text Encoding Conversion Manager
|
||||
* when it's available, and have our own routines for converting to
|
||||
* standard Mac OS scripts when it's not. Support for ATSUI might be
|
||||
* nice, too.
|
||||
*/
|
||||
|
||||
int is_dbcs_leadbyte(int codepage, char byte)
|
||||
{
|
||||
return 0; /* we don't do DBCS */
|
||||
}
|
||||
|
||||
int mb_to_wc(int codepage, int flags, char *mbstr, int mblen,
|
||||
wchar_t *wcstr, int wclen)
|
||||
{
|
||||
int ret = 0;
|
||||
while (mblen > 0 && wclen > 0) {
|
||||
*wcstr++ = (unsigned char) *mbstr++;
|
||||
mblen--, wclen--, ret++;
|
||||
}
|
||||
return ret; /* FIXME: check error codes! */
|
||||
}
|
||||
|
||||
int wc_to_mb(int codepage, int flags, wchar_t *wcstr, int wclen,
|
||||
char *mbstr, int mblen, char *defchr, int *defused)
|
||||
{
|
||||
int ret = 0;
|
||||
if (defused)
|
||||
*defused = 0;
|
||||
while (mblen > 0 && wclen > 0) {
|
||||
if (*wcstr >= 0x100) {
|
||||
if (defchr)
|
||||
*mbstr++ = *defchr;
|
||||
else
|
||||
*mbstr++ = '.';
|
||||
if (defused)
|
||||
*defused = 1;
|
||||
} else
|
||||
*mbstr++ = (unsigned char) *wcstr;
|
||||
wcstr++;
|
||||
mblen--, wclen--, ret++;
|
||||
}
|
||||
return ret; /* FIXME: check error codes! */
|
||||
}
|
||||
|
||||
void init_ucs(void)
|
||||
{
|
||||
int i;
|
||||
/* Find the line control characters. FIXME: this is not right. */
|
||||
for (i = 0; i < 256; i++)
|
||||
if (i < ' ' || (i >= 0x7F && i < 0xA0))
|
||||
unitab_ctrl[i] = i;
|
||||
else
|
||||
unitab_ctrl[i] = 0xFF;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
unitab_line[i] = unitab_scoacs[i] = i;
|
||||
unitab_xterm[i] = (i >= 0x5F && i < 0x7F) ? ((i+1) & 0x1F) : i;
|
||||
}
|
||||
}
|
7
putty.h
7
putty.h
@ -502,6 +502,13 @@ enum { PKT_INCOMING, PKT_OUTGOING };
|
||||
void log_packet(void *logctx, int direction, int type,
|
||||
char *texttype, void *data, int len);
|
||||
|
||||
/*
|
||||
* Exports from testback.c
|
||||
*/
|
||||
|
||||
extern Backend null_backend;
|
||||
extern Backend loop_backend;
|
||||
|
||||
/*
|
||||
* Exports from raw.c.
|
||||
*/
|
||||
|
@ -6,6 +6,10 @@
|
||||
#include <windows.h>
|
||||
#include "winstuff.h"
|
||||
|
||||
#elif defined(macintosh)
|
||||
|
||||
#include "macstuff.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "unix.h"
|
||||
|
@ -484,6 +484,8 @@ void load_settings(char *section, int do_host, Config * cfg)
|
||||
gppi(sesskey, "TermHeight", 24, &cfg->height);
|
||||
#ifdef _WINDOWS
|
||||
gpps(sesskey, "Font", "Courier New", cfg->font, sizeof(cfg->font));
|
||||
#elif defined(macintosh)
|
||||
gpps(sesskey, "Font", "Monaco", cfg->font, sizeof(cfg->font));
|
||||
#else
|
||||
gpps(sesskey, "Font", "fixed", cfg->font, sizeof(cfg->font));
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user