Revision 60b5e2779508ed4effa3994d71251b9b5f67076b authored by Barak A. Pearlmutter on 13 January 2022, 14:08:22 UTC, committed by Barak A. Pearlmutter on 13 January 2022, 14:08:22 UTC
1 parent eb3f51e
macterm.c
/*
* macterm.c macintosh screen module mak
*
* Copyright (C) 1993 by the Regents of the University of California
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "logo.h"
#include "globals.h"
#include "macterm.h"
#include <console.h>
#include <math.h>
#include <Sound.h>
#include <Types.h>
#include <GestaltEqu.h>
#include <Palettes.h>
#include <Files.h>
#include <Fonts.h>
char *LogoPlatformName="MacOS-Classic";
char windowtitle[100];
FILE *graphics, *console;
WindowPtr graphics_window, listener_window;
GrafPtr savePort;
extern WindowPtr myWindow; /* the editor window */
FIXNUM pen_color = 7, back_ground = 0;
/************************************************************/
void nop() {
}
int can_do_color = 0, want_color = 0;
PaletteHandle the_palette;
void get_can_do_color(void) {
long ans;
if (!Gestalt(gestaltQuickdrawVersion, &ans))
can_do_color = (ans != 0);
}
void init_mac_memory(void) {
unsigned long AZ, AL;
/* SetApplLimit((Ptr)(GetApplLimit() - 150000L)); MaxApplZone(); */
AL = (unsigned long)GetApplLimit(); AZ = (unsigned long)ApplicZone();
/* SetApplLimit((Ptr) ( (AZ + ((AL-AZ)*3)/4) & 0x00fffffe )); */
/* SetApplLimit((Ptr)(AZ + 300000L)); */
SetApplLimit((Ptr)((AZ + ((AL-AZ)*3)/4) & -2L)); /* PCB */
MaxApplZone();
}
BOOLEAN check_mac_stop(void) {
char the_key_map[16];
static int full = 400;
static int gotkey = 0;
extern void ProcessEvent(void);
if (FreeMem() < 3000) {
err_logo(STACK_OVERFLOW, NIL);
return(1);
}
GetKeys((unsigned long *)&the_key_map);
if (the_key_map[5] & 128 && the_key_map[6] & 128) {
/* period and command are down */
if (!gotkey) {
gotkey = 1;
FlushEvents(everyEvent, 0);
#ifdef SIG_TAKES_ARG
logo_stop(0);
#else
logo_stop();
#endif
return 1;
}
} else if (the_key_map[5] & 8 && the_key_map[6] & 128) {
/* comma and command are down */
if (!gotkey) {
gotkey = 1;
FlushEvents(everyEvent, 0);
#ifdef SIG_TAKES_ARG
logo_pause(0);
#else
logo_pause();
#endif
}
} else
gotkey = 0;
if (--full == 0) {
ProcessEvent();
full = 400;
}
return(0);
}
void term_init_mac(void) {
MenuHandle menu_handle;
get_can_do_color();
tty_charmode = 0;
x_max = 80;
y_max = 24;
console_options.title = (unsigned char *)windowtitle;
console_options.top-= 5;
console_options.left-= 5;
strncpy((char *)console_options.title, (char const *)"\pGraphics", 9);
want_color = 1;
graphics = fopenc();
want_color = 0;
cgotoxy(1, 1, graphics);
graphics_window = FrontWindow();
if (can_do_color) {
the_palette = GetNewPalette(131);
SetPalette(graphics_window, the_palette, 1);
ActivatePalette(graphics_window);
}
SizeWindow(graphics_window, graphics_window->portRect.right,
graphics_window->portRect.bottom - 1, 0);
cs_helper(TRUE);
console_options.top+= 10;
console_options.left+= 10;
strncpy((char *)console_options.title, (char const *)"\pBerkeley Logo", 14);
console = fopenc();
lregulartext(NIL);
cinverse(1,stdout);
listener_window = FrontWindow();
console_options.title[0] = 0;
menu_handle = GetMHandle(3);
AppendMenu(menu_handle,
"\p(-;(Accept Editor Changes/A;(Cancel Editor Changes");
AppendMenu(menu_handle, "\p(-;(Page Setup;(Print/P");
SetUpWindows();
prepare_to_draw;
mac_set_bg(0L);
mac_set_pc(7L);
save_color();
done_drawing;
x_coord = y_coord = 0;
so_arr[0] = '\1'; so_arr[1] = '\0';
se_arr[0] = '\2'; se_arr[1] = '\0';
}
void mac_gotoxy(int x, int y) {
/* 4.4
if (x_coord < 0) x_coord = 0;
if (x_coord >= console_options.ncols) x_coord = console_options.ncols - 1;
if (y_coord < 0) y_coord = 0;
if (y_coord >= console_options.nrows) y_coord = console_options.nrows - 1;
*/
cgotoxy(x_coord + 1, y_coord + 1, stdout);
}
/************************************************************/
/* These are primitives that can only exist on the mac and/or are ad hoc
things Michael invented that we probably don't want to keep around in Berkeley Logo. */
NODE *lsetwindowtitle(NODE *arg) {
NODE *name;
name = string_arg(arg);
if (name != UNBOUND) {
noparity_strnzcpy((char *)(windowtitle + 1), getstrptr(name), (int)getstrlen(name));
windowtitle[0] = (char)getstrlen(name);
}
return(UNBOUND);
}
void option_helper(short* var, NODE *arg) {
NODE *val;
val = integer_arg(arg);
if (NOT_THROWING)
*var = (short)getint(val);
}
NODE *lsettextfont(NODE *arg) {
option_helper(&console_options.txFont, arg);
return(UNBOUND);
}
NODE *lsettextsize(NODE *arg) {
option_helper(&console_options.txSize, arg);
return(UNBOUND);
}
NODE *lsettextstyle(NODE *arg) {
option_helper(&console_options.txFace, arg);
return(UNBOUND);
}
NODE *lsetwindowsize(NODE *args) {
NODE *xnode, *ynode = UNBOUND, *arg;
arg = pos_int_vector_arg(args);
if (NOT_THROWING) {
xnode = car(arg);
ynode = cadr(arg);
console_options.ncols = max((int)getint(xnode), 40);
console_options.nrows = max((int)getint(ynode), 5);
}
return(UNBOUND);
}
NODE *lsetwindowxy(NODE *args) {
NODE *xnode, *ynode = UNBOUND, *arg;
arg = pos_int_vector_arg(args);
if (NOT_THROWING) {
xnode = car(arg);
ynode = cadr(arg);
console_options.left = (int)getint(xnode);
console_options.top = (int)getint(ynode);
}
return(UNBOUND);
}
NODE *lnewconsole(NODE *args) {
FILE *c, *old;
int was_graphics;
was_graphics = (FrontWindow() == graphics_window);
chide(stdin);
fclose(stdin);
fclose(stdout);
fclose(stderr);
c = fopenc();
fclose(stdin);
fclose(stdout);
freopenc(c, stdin);
freopenc(c, stdout);
freopenc(c, stderr);
lcleartext(NIL);
cinverse(1,stdout);
if (was_graphics) {
graphics_window = FrontWindow();
graphics = c;
} else {
listener_window = FrontWindow();
console = c;
x_max = console_options.ncols;
y_max = console_options.nrows;
}
return(UNBOUND);
}
NODE *lgraphtext(NODE *args) {
freopenc(graphics, stdin);
freopenc(graphics, stdout);
freopenc(graphics, stderr);
return(UNBOUND);
}
NODE *lregulartext(NODE *args) {
freopenc(console, stdin);
freopenc(console, stdout);
freopenc(console, stderr);
return(UNBOUND);
}
NODE *lcaninverse(NODE *args) {
FIXNUM onoff = int_arg(args);
if (NOT_THROWING) cinverse(onoff, stdin);
return(UNBOUND);
}
/************************************************************/
/* These are the machine-specific graphics definitions. All versions must provide
a set of functions analogous to these. */
void save_pen(pen_info *p) {
GetPort(&savePort);
SetPort(graphics_window);
GetPenState(&(p->ps));
p->vis = graphics_window->pnVis;
// p->color = graphics_window->fgColor;
p->color = pen_color;
SetPort(savePort);
}
void restore_pen(pen_info *p) {
GetPort(&savePort);
SetPort(graphics_window);
SetPenState(&(p->ps));
graphics_window->pnVis = p->vis;
// graphics_window->fgColor = p->color;
mac_set_pc(p->color);
SetPort(savePort);
}
void plain_xor_pen(void) {
PenNormal();
PenMode(patXor);
}
FIXNUM color_table[8] = {33, 409, 341, 273, 205, 137, 69, 30};
FIXNUM hw_color(FIXNUM c) {
if (c >= 0 && c < 8) return color_table[c];
if (c < 0) return c;
return c-8;
}
int palette_color(FIXNUM c) {
if (c == 7) return 0;
if (c >= 0 && c < 7) return c+1;
return c;
}
void mac_set_pc(FIXNUM c) {
pen_color = c;
if (can_do_color)
PmForeColor(palette_color(c+2));
else
graphics_window->fgColor = hw_color(c);
}
void mac_set_bg(FIXNUM c) {
back_ground = c;
if (can_do_color)
PmBackColor(palette_color(c+2));
else
graphics_window->bkColor = hw_color(c);
redraw_graphics();
}
void set_palette(int slot, unsigned int r, unsigned int g, unsigned int b) {
RGBColor rgb;
if (can_do_color) {
slot+=2;
rgb.red = r;
rgb.green = g;
rgb.blue = b;
SetEntryColor(the_palette, slot, &rgb);
SetEntryUsage(the_palette, slot, pmTolerant, 2000);
ActivatePalette(graphics_window);
redraw_graphics();
}
}
void get_palette(int slot, unsigned int *r, unsigned int *g, unsigned int *b) {
RGBColor rgb;
if (can_do_color) {
slot+=2;
GetEntryColor(the_palette, palette_color((FIXNUM)slot), &rgb);
*r = rgb.red;
*g = rgb.green;
*b = rgb.blue;
} else {
*r = (slot&4 ? 65000 : 0);
*g = (slot&2 ? 65000 : 0);
*b = (slot&1 ? 65000 : 0);
}
}
void set_pen_pattern(char *pat) {
PenPat((struct Pattern *)pat);
}
void set_list_pen_pattern(NODE *arg) {
NODE *cur_num, *temp;
char p_arr[8];
int count;
cur_num = arg;
for (count = 0 ; count <= 7 && cur_num != NIL && NOT_THROWING ; count++) {
temp = cnv_node_to_numnode(car(cur_num));
p_arr[count] = (char)getint(temp);
cur_num = cdr(cur_num);
}
PenPat((struct Pattern *)p_arr);
}
#ifdef SYMANTEC_C
union myPattU {
char patt_ch[8];
struct Pattern patt_p;
};
typedef union myPattU myPatt;
void get_pen_pattern(char *pat) {
PenState oil;
int count;
myPatt my_patt;
GetPenState(&oil);
my_patt.patt_p = oil.pnPat;
for (count = 0; count < 8; count++)
*(char *)(pat + count) = my_patt.patt_ch[count];
}
NODE *Get_node_pen_pattern() {
PenState oil;
int count;
myPatt my_patt;
GetPenState(&oil);
my_patt.patt_p = oil.pnPat;
return(cons(make_intnode((FIXNUM)(my_patt.patt_ch[0])),
cons(make_intnode((FIXNUM)(my_patt.patt_ch[1])),
cons(make_intnode((FIXNUM)(my_patt.patt_ch[2])),
cons(make_intnode((FIXNUM)(my_patt.patt_ch[3])),
cons(make_intnode((FIXNUM)(my_patt.patt_ch[4])),
cons(make_intnode((FIXNUM)(my_patt.patt_ch[5])),
cons(make_intnode((FIXNUM)(my_patt.patt_ch[6])),
cons(make_intnode((FIXNUM)(my_patt.patt_ch[7])),
NIL)))))))));
}
#else
void get_pen_pattern(char *pat) {
PenState oil;
int count;
GetPenState(&oil);
for (count = 0; count < 8; count++)
*(char *)(pat + count) = oil.pnPat[count];
}
NODE *Get_node_pen_pattern() {
PenState oil;
int count;
GetPenState(&oil);
return(cons(make_intnode((FIXNUM)(oil.pnPat[0])),
cons(make_intnode((FIXNUM)(oil.pnPat[1])),
cons(make_intnode((FIXNUM)(oil.pnPat[2])),
cons(make_intnode((FIXNUM)(oil.pnPat[3])),
cons(make_intnode((FIXNUM)(oil.pnPat[4])),
cons(make_intnode((FIXNUM)(oil.pnPat[5])),
cons(make_intnode((FIXNUM)(oil.pnPat[6])),
cons(make_intnode((FIXNUM)(oil.pnPat[7])),
NIL)))))))));
}
#endif
void label(char *s) {
short tmode;
GetPort(&savePort);
SetPort(graphics_window);
MoveTo(g_round(graphics_window->portRect.right/2.0 + turtle_x),
g_round(graphics_window->portRect.bottom/2.0 - turtle_y));
switch(pen_mode) {
case patCopy : tmode = srcOr; break;
case patBic : tmode = srcBic; break;
case patXor : tmode = srcXor; break;
default : tmode = srcCopy; break; /* can't happen */
}
TextFont(monaco); TextSize(9); TextMode(tmode);
DrawString((unsigned char const *)s);
SetPort(savePort);
}
void logofill(void) {
BitMap mask;
if (can_do_color) {
prepare_to_draw;
mask.bounds = (*(graphics_window->visRgn))->rgnBBox;
mask.bounds.right = mask.bounds.right - mask.bounds.left;
mask.bounds.left = 0;
mask.bounds.bottom = mask.bounds.bottom - mask.bounds.top;
mask.bounds.top = 0;
mask.rowBytes = ((mask.bounds.right + 15) / 8) & ~1;
mask.baseAddr = malloc(mask.rowBytes * mask.bounds.bottom);
if (mask.baseAddr == NULL) {
err_logo(OUT_OF_MEM, NIL);
done_drawing;
return;
}
SeedCFill(&(graphics_window->portBits), &mask,
&((*(graphics_window->visRgn))->rgnBBox),
&(mask.bounds),
graphics_window->pnLoc.h, graphics_window->pnLoc.v,
0, 0L);
CopyMask(&mask, &mask, &(graphics_window->portBits),
&(mask.bounds), &(mask.bounds),
&((*(graphics_window->visRgn))->rgnBBox));
free(mask.baseAddr);
done_drawing;
}
}
void erase_screen(void) {
int old_vis;
GetPort(&savePort);
SetPort(graphics_window);
old_vis = graphics_window->pnVis;
graphics_window->pnVis = 0;
EraseRect(&graphics_window->portRect);
graphics_window->pnVis = old_vis;
SetPort(savePort);
}
void t_screen(void) {
SelectWindow(listener_window);
console_options.ncols = 80;
console_options.nrows = 25;
console_options.left = 15;
console_options.top = 55;
strncpy((char *)console_options.title, (char *)"\pBerkeley Logo", 14);
lnewconsole(NIL);
MoveWindow(myWindow, 15, 55, TRUE);
MySizeWindow(myWindow, 488, 283);
SelectWindow(listener_window);
myGrow(listener_window, (listener_window == FrontWindow()));
}
void s_screen(void) {
Rect bounds;
int v;
if (can_do_color)
v = ((*(((CGrafPtr)graphics_window)->portPixMap))->bounds.bottom -
(*(((CGrafPtr)graphics_window)->portPixMap))->bounds.top) - 84;
else
v = (graphics_window->portBits.bounds.bottom -
graphics_window->portBits.bounds.top) - 84;
SelectWindow(listener_window);
console_options.ncols = 80;
console_options.nrows = 6;
console_options.left = 5;
console_options.top = v + 6;
strncpy((char *)console_options.title, (char *)"\pBerkeley Logo", 14);
lnewconsole(NIL);
MoveWindow(myWindow, 5, v, TRUE);
MySizeWindow(myWindow, 488, 80);
SelectWindow(listener_window);
myGrow(listener_window, (listener_window == FrontWindow()));
}
void f_screen(void) {
Rect bounds;
int v;
if (can_do_color)
v = ((*(((CGrafPtr)graphics_window)->portPixMap))->bounds.bottom -
(*(((CGrafPtr)graphics_window)->portPixMap))->bounds.top) - 84;
else
v = (graphics_window->portBits.bounds.bottom -
graphics_window->portBits.bounds.top) - 84;
SelectWindow(listener_window);
console_options.ncols = 80;
console_options.nrows = 0;
console_options.left = 5;
console_options.top = v + 52;
strncpy((char *)console_options.title, (char *)"\pBerkeley Logo", 14);
lnewconsole(NIL);
MoveWindow(myWindow, 5, v, TRUE);
MySizeWindow(myWindow, 488, 80);
SelectWindow(graphics_window);
myGrow(graphics_window, (graphics_window == FrontWindow()));
}
int in_fscreen(void) {
return (console_options.nrows == 0);
}
FIXNUM mickey_x(void) {
Point the_mouse;
GetPort(&savePort);
SetPort(graphics_window);
GetMouse(&the_mouse);
SetPort(savePort);
return((FIXNUM)(the_mouse.h - graphics_window->portRect.right/2));
}
FIXNUM mickey_y(void) {
Point the_mouse;
GetPort(&savePort);
SetPort(graphics_window);
GetMouse(&the_mouse);
SetPort(savePort);
return((FIXNUM)(graphics_window->portRect.bottom/2 - the_mouse.v));
}
#ifdef SYMANTEC_C
SndChannelPtr SoundChannel = NIL;
#endif
/* see Inside Macintosh vol. 2 pp. 237-241 for pitch values */
void tone(FIXNUM pitch, FIXNUM duration) {
#ifndef SYMANTEC_C
struct { int mode;
int freq;
int amp;
int dur;
} sound_rec;
sound_rec.mode = -1;
sound_rec.freq = (int)(387205L/pitch);
sound_rec.amp = 200;
sound_rec.dur = (int)duration;
StartSound(&sound_rec, (long)8, (char *)(-1));
while (!SoundDone()) ;
#endif
#ifdef SYMANTEC_C
SndCommand MyCommand;
SCStatus ChannelStatus;
pitch = (int) 60+((log(pitch/261.625))/(log(twelfthRootTwo)));
duration *= 34; /* ticks to half-milliseconds */
if (duration>0 && duration<65536 && pitch >=0 && pitch<128) {
if (SoundChannel == NIL) {
SndNewChannel(&SoundChannel, squareWaveSynth,
initMono+initChanLeft, (ProcPtr)NIL);
}
if (SoundChannel != NIL) {
MyCommand.cmd = freqDurationCmd;
MyCommand.param1 = duration;
MyCommand.param2 = pitch;
SndDoImmediate(SoundChannel, &MyCommand);
ChannelStatus.scChannelBusy = true;
while (ChannelStatus.scChannelBusy == true)
SndChannelStatus(SoundChannel, sizeof(ChannelStatus),
&ChannelStatus);
}
}
#endif
}
/************************************************************/
void c_to_pascal_string(char *str, int len) {
int count = len;
char prev;
while (count > 0) {
prev = str[count - 1];
str[count] = clearparity(prev);
count--;
}
str[0] = len;
}
void fixMacType(NODE *arg) {
char *fnstr;
FSSpec theFSSpec;
arg = cnv_node_to_strnode(car(arg));
if (arg == UNBOUND) return;
fnstr = (char *) malloc((size_t)getstrlen(arg) + 1);
if (fnstr == NULL) {
err_logo(FILE_ERROR, make_static_strnode("Not enough memory"));
return;
}
noparity_strnzcpy(fnstr, getstrptr(arg), getstrlen(arg));
c_to_pascal_string(fnstr, getstrlen(arg));
FSMakeFSSpec(0, 0L, (unsigned char *)fnstr, &theFSSpec);
HCreate(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name, '????', 'EPSF');
}
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...