This is sq-code.txt in view mode; [Download] [Up]
#if 0
/* sqNeXTSTEP.c -- support for the NeXTSTEP GUI.
*
* Author: Pascal Bourguignon <pjb@imaginet.fr>
*
* Last edited: Thu Jun 11 06:57:17 MET 1998
*
* BUGS: this file is too long; it should be split into two.
*
* $Log: sqNeXTSTEP.c,v $
*/
static char *rcsid=
"$Id:$";
#include "sq.h"
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/param.h>
#include <unistd.h>
#include <errno.h>
/*** Variables -- image and path names ***/
#define IMAGE_NAME_SIZE MAXPATHLEN
char imageName[MAXPATHLEN+1]; /* full path to image */
char shortImageName[MAXPATHLEN+1]; /* just the base name */
char vmPath[MAXPATHLEN+1]; /* full path to interpreter's directory */
int initialHeapSize; /* 5 megabytes by default */
int initialArgc;
char **initialArgv;
#ifndef HEADLESS
/*** Variables -- X11 Related ***/
/* name of Squeak windows in Xrm and the WM */
#define xClassName "Squeak"
char *displayName= 0; /* name of display,or 0 for $DISPLAY */
Display *stDisplay= null; /* Squeak display */
int stXfd= 0; /* X connection file descriptor */
Window stWindow= null; /* Squeak window */
Visual *stVisual; /* the default visual */
GC stGC; /* graphics context used for rendering */
Colormap stColormap= null; /* Squeak color map */
int stDisplayBitsIndex= 0; /* last known oop of the VM's Display */
XImage *stImage= 0; /* ...and it's client-side pixmap */
char *stPrimarySelection; /* buffer holding selection */
char *stEmptySelection= ""; /* immutable "empty string" value */
int stPrimarySelectionSize;/* size of buffer holding selection */
int stOwnsSelection= 0; /* true if we own the X selection */
XColor stColorBlack; /* black pixel value in stColormap */
XColor stColorWhite; /* white pixel value in stColormap */
int savedWindowSize= 0; /* initial size of window */
int savedWindowOrigin= -1; /* initial origin of window */
XPoint mousePosition; /* position at last PointerMotion event */
Time stButtonTime; /* time of last ButtonRelease (for SetSeln) */
# ifdef USE_XSHM
XShmSegmentInfo stShmInfo; /* shared memory descriptor */
int completions= 0; /* outstanding completion events */
int completionType; /* the type of XShmCompletionEvent */
int useXshm= 0; /* 1 if shared memory is in use */
int asyncUpdate= 0; /* 1 for asynchronous screen updates */
# endif
int stDepth;
int stBitsPerPixel= 0;
unsigned int stColors[256];
unsigned int stDownGradingColors[256];
int stHasSameRGBMask16;
int stHasSameRGBMask32;
int stRNMask,stGNMask,stBNMask;
int stRShift,stGShift,stBShift;
char *stDisplayBitmap= 0;
#endif
int sleepWhenUnmapped= 0;
int noTitle= 0;
int fullScreen= 0;
struct timeval startUpTime;
/* maximum input polling frequency */
#define MAXPOLLSPERSEC 33
#ifndef HEADLESS
/* we are interested in these events */
#define EVENTMASK ButtonPressMask | ButtonReleaseMask | \
KeyPressMask | PointerMotionMask | \
ExposureMask | StructureNotifyMask
/* largest X selection that we will attempt to handle (bytes) */
#define MAX_SELECTION_SIZE 100*1024
/* longest we're prepared to wait for the selection owner to convert it (seconds) */
#define SELECTION_TIMEOUT 3
/*** Variables -- Event Recording ***/
#define KEYBUF_SIZE 64
int keyBuf[KEYBUF_SIZE]; /* circular buffer */
int keyBufGet= 0; /* index of next item of keyBuf to read */
int keyBufPut= 0; /* index of next item of keyBuf to write */
int keyBufOverflows= 0; /* number of characters dropped */
int buttonState= 0; /* mouse button and modifier state when mouse
button went down or 0 if not pressed */
/* This table maps the X modifier key bits to 4 Squeak modifier
bits. (The X caps lock key is mapped as shift,meta is
mapped to command,and ctrl+meta is mapped to option.
X bits: <meta><control><shift-lock><shift>
Squeak bits: <command><option><control><shift>
*/
char modifierMap[16]= {
0,1,1,0,2,3,3,2,8,9,9,8,4,5,5,4
};
/* masks for the XButtonEvent modifier state */
#define MOD_SHIFT 1
#define MOD_CONTROL 4
#define MOD_META 8
#endif
/*** Functions ***/
#ifdef ioMSecs
# undef ioMSecs
#endif
int HandleEvents(void);
void RecordFullPathForImageName(char *localImageName);
void SetUpTimers(void);
void usage(void);
void imageNotFound(char *imageName);
void ParseArguments(int argc,char **argv);
void segv(int ignored);
#ifndef HEADLESS
void SetColorEntry(int index,int red,int green,int blue);
void SetUpClipboard(void);
void SetUpPixmap(void);
void SetUpWindow(char *displayName);
void SetWindowSize(void);
void getMaskbit(unsigned long ul,int *nmask,int *shift);
void setupDownGradingColors(void);
void copyReverseImageBytes(int *fromImageData,int *toImageData,
int depth,int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB);
void copyReverseImageWords(int *fromImageData,int *toImageData,
int depth,int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB);
# define declareCopyFunction(NAME) \
void NAME (int *fromImageData,int *toImageData,\
int width,int height,\
int affectedL,int affectedT,int affectedR,int affectedB)
declareCopyFunction(copyImage8To8);
declareCopyFunction(copyImage8To16);
declareCopyFunction(copyImage16To8);
declareCopyFunction(copyImage8To32);
declareCopyFunction(copyImage32To8);
declareCopyFunction(copyImage16To32);
declareCopyFunction(copyImage32To16);
declareCopyFunction(copyImage16To16);
declareCopyFunction(copyImage32To32);
# undef declareCopyFunction
void ux2st(char *string);
void st2ux(char *string);
void claimSelection(void);
void sendSelection(XSelectionRequestEvent *requestEv);
char *getSelection(void);
static void redrawDisplay(int l,int r,int t,int b);
static int translateCode(KeySym symbolic);
void recordKeystroke(XKeyEvent *theEvent);
void recordMouseDown(XButtonEvent *theEvent);
void recordModifierButtons(XButtonEvent *theEvent);
# ifdef USE_XSHM
int XShmGetEventBase(Display *);
# endif
int ioMSecs(void);
#endif !HEADLESS
int strtobkm(char *str);
extern void aioPollForIO(int,int); /* see sqUnixNetwork.c */
#ifndef HEADLESS
/*** line-end conventions (mainly for converting the X selection) ***/
void st2ux(char *string)
{
if (!string) return;
while (*string)
{
if (*string == '\r')
*string= '\n';
string++;
}
}
void ux2st(char *string)
{
if (!string) return;
while (*string)
{
if (*string == '\n')
*string= '\r';
string++;
}
}
/*** X-related Functions ***/
void claimSelection(void)
{
XSetSelectionOwner(stDisplay,XA_PRIMARY,stWindow,CurrentTime);
stOwnsSelection= (XGetSelectionOwner(stDisplay,XA_PRIMARY) == stWindow);
}
void sendSelection(XSelectionRequestEvent *requestEv)
{
XSelectionEvent notifyEv;
/* this should REFUSE the selection if the target type isn't XA_STRING */
st2ux(stPrimarySelection);
XChangeProperty(requestEv->display,
requestEv->requestor,
(requestEv->property == None
? requestEv->target
: requestEv->property),
requestEv->target,
8,PropModeReplace,stPrimarySelection,
(stPrimarySelection ? strlen(stPrimarySelection) : 0));
ux2st(stPrimarySelection);
notifyEv.type= SelectionNotify;
notifyEv.display= requestEv->display;
notifyEv.requestor= requestEv->requestor;
notifyEv.selection= requestEv->selection;
notifyEv.target= requestEv->target;
notifyEv.time= requestEv->time;
notifyEv.property= (requestEv->property == None)
? requestEv->target
: requestEv->property;
XSendEvent(requestEv->display,requestEv->requestor,
False,0,(XEvent *)¬ifyEv);
XFlush(stDisplay);
}
char *getSelection(void)
{
XEvent ev;
fd_set fdMask;
char *data;
/* request the selection */
XConvertSelection(stDisplay,XA_PRIMARY,XA_STRING,XA_STRING,stWindow,CurrentTime);
/* wait for selection notification,ignoring (most) other events. */
FD_ZERO(&fdMask);
FD_SET(stXfd,&fdMask);
do {
if (XPending(stDisplay) == 0)
{
int status;
struct timeval timeout= {SELECTION_TIMEOUT,0};
while ((status= select(FD_SETSIZE,&fdMask,0,0,&timeout)) < 0
&& errno == EINTR);
if (status < 0)
{
perror("select(stDisplay)");
return stEmptySelection;
}
if (status == 0)
{
XBell(stDisplay,0);
return stEmptySelection;
}
}
XNextEvent(stDisplay,&ev);
/* this is necessary so that we can supply our own selection when we
are the requestor -- this could (should) be optimised to return the
stored selection value instead! */
if (ev.type == SelectionRequest) sendSelection(&ev.xselectionrequest);
# ifdef USE_XSHM
if (ev.type == completionType) --completions;
# endif
} while (ev.type != SelectionNotify);
/* check if the selection was refused */
if (ev.xselection.property == None)
{
XBell(stDisplay,0);
return stEmptySelection;
}
/* get the value of the selection from the containing property */
{
Atom type;
int format;
unsigned long nitems,bytesAfter;
XGetWindowProperty(stDisplay,ev.xselection.requestor,ev.xselection.property,
(long)0,(long)(MAX_SELECTION_SIZE/4),
False,AnyPropertyType,
&type,&format,&nitems,&bytesAfter,
(unsigned char **)&data);
if (bytesAfter > 0)
XBell(stDisplay,0);
}
/* return the selection -- which must be XFreed() when no longer needed! */
return data;
}
/* a modified copy of fullDisplayUpdate() that redraws
only the damaged parts of the window according to each
expose event on the queue.
Note: if the format of Form or Bitmap changes,or if
the special object index of Display is changed,this
version of the code WILL FAIL! Otherwise it is to be
preferred.
*/
static void redrawDisplay(int l,int r,int t,int b)
{
extern int specialObjectsOop;
extern int lengthOf(int);
# define longAt(i) (*((int *) (i)))
int displayObj= longAt((specialObjectsOop + 4) + (14 * 4));
if ((((((unsigned)(longAt(displayObj))) >> 8) & 15) <= 4) &&
((lengthOf(displayObj)) >= 4))
{
int dispBits= longAt((displayObj + 4) + (0 * 4));
int w= fetchIntegerofObject(1,displayObj);
int h= fetchIntegerofObject(2,displayObj);
int d= fetchIntegerofObject(3,displayObj);
int dispBitsIndex= dispBits + 4;
ioShowDisplay(dispBitsIndex,w,h,d,l,r,t,b);
}
# undef longAt
}
#endif !HEADLESS
#ifndef HEADLESS
void getMaskbit(unsigned long ul,int *nmask,int *shift)
{
int i;
unsigned long hb;
*nmask= *shift= 0;
hb= 0x8000; hb= (hb<<16); /* hb = 0x80000000UL */
for (i= 31; ((ul & hb) == 0) && i >= 0; --i,ul<<= 1)
;
for (; ((ul & hb) != 0) && i >= 0; --i,ul<<= 1)
(*nmask)++;
*shift= i+1;
}
void setupDownGradingColors(void)
{
int r,g,b,i;
for (r= 0; r < 0x8; r++)
{
for (g= 0; g < 0x8; g++)
{
for (b= 0; b < 0x4; b++)
{
int mindiff= 0x7*0x7 + 0x7*0x7 + 0x3*0x3 + 1;
for (i= 0; i < 256; i++)
{
int rdiff,gdiff,bdiff,diff;
rdiff= r - ((stColors[i]>>5) & 0x7);
gdiff= g - ((stColors[i]>>2) & 0x7);
bdiff= b - (stColors[i] & 0x3);
diff= rdiff*rdiff + gdiff*gdiff + bdiff*bdiff;
if (diff < mindiff)
{
mindiff= diff;
stDownGradingColors[(r << 5) + (g << 2) + b] = i;
}
}
}
}
}
}
void SetColorEntry(int index,int red,int green,int blue)
{
if (index >= 256)
return;
if (stVisual->class == TrueColor || stVisual->class == DirectColor)
{
unsigned int r,g,b;
r= red;
g= green;
b= blue;
stColors[index]= (((r>>(16-stRNMask))<<stRShift) |
((g>>(16-stGNMask))<<stGShift) |
((b>>(16-stBNMask))<<stBShift));
}
else
{
XColor color;
color.pixel= index;
color.red= red;
color.green= green;
color.blue= blue;
color.flags= DoRed|DoGreen|DoBlue;
XStoreColor(stDisplay,stColormap,&color);
/* map rgb weight=332 */
stColors[index] = ((((unsigned int)red >>(16-3))<<5) |
(((unsigned int)green>>(16-3))<<2) |
((unsigned int)blue >>(16-2)));
}
}
void SetUpPixmap(void)
{
int count;
XPixmapFormatValues *xpv;
stVisual= DefaultVisual(stDisplay,DefaultScreen(stDisplay));
stDepth= DefaultDepth(stDisplay,DefaultScreen(stDisplay));
xpv= XListPixmapFormats(stDisplay,&count);
if (xpv)
{
while(--count >= 0)
{
if (stDepth == xpv[count].depth)
stBitsPerPixel= xpv[count].bits_per_pixel;
}
XFree((void*)xpv);
}
if (stBitsPerPixel == 0)
stBitsPerPixel= stDepth;
switch (stVisual->class)
{
case PseudoColor:
if (stBitsPerPixel == 8)
break;
else
{
fprintf(stderr,"This visual class is not supported\n");
exit(1);
return;
}
case TrueColor:
case DirectColor:
getMaskbit(stVisual->red_mask, &stRNMask,&stRShift);
getMaskbit(stVisual->green_mask,&stGNMask,&stGShift);
getMaskbit(stVisual->blue_mask, &stBNMask,&stBShift);
if (stBitsPerPixel == 16)
{
stHasSameRGBMask16= (stVisual->red_mask == (0x1f << 10) &&
stVisual->green_mask == (0x1f << 5) &&
stVisual->blue_mask == (0x1f));
break;
}
else if (stBitsPerPixel == 32)
{
stHasSameRGBMask32= (stVisual->red_mask == (0xff << 16) &&
stVisual->green_mask == (0xff << 8) &&
stVisual->blue_mask == (0xff));
break;
}
else
{
fprintf(stderr,"This visual class is not supported\n");
exit(1);
return;
}
case GrayScale:
case StaticColor:
case StaticGray:
default:
fprintf(stderr,"This visual class is not supported\n");
exit(1);
return;
}
if (stVisual->class == PseudoColor)
stColormap= XCreateColormap(stDisplay,
stWindow,
DefaultVisual(stDisplay,DefaultScreen(stDisplay)),
AllocAll);
/* 1-bit colors (monochrome) */
SetColorEntry(0,65535,65535,65535); /* white or transparent */
SetColorEntry(1, 0, 0, 0); /* black */
/* additional colors for 2-bit color */
SetColorEntry(2,65535,65535,65535); /* opaque white */
SetColorEntry(3,32768,32768,32768); /* 1/2 gray */
/* additional colors for 4-bit color */
SetColorEntry( 4,65535, 0, 0); /* red */
SetColorEntry( 5, 0,65535, 0); /* green */
SetColorEntry( 6, 0, 0,65535); /* blue */
SetColorEntry( 7, 0,65535,65535); /* cyan */
SetColorEntry( 8,65535,65535, 0); /* yellow */
SetColorEntry( 9,65535, 0,65535); /* magenta */
SetColorEntry(10, 8192, 8192, 8192); /* 1/8 gray */
SetColorEntry(11,16384,16384,16384); /* 2/8 gray */
SetColorEntry(12,24576,24576,24576); /* 3/8 gray */
SetColorEntry(13,40959,40959,40959); /* 5/8 gray */
SetColorEntry(14,49151,49151,49151); /* 6/8 gray */
SetColorEntry(15,57343,57343,57343); /* 7/8 gray */
/* additional colors for 8-bit color */
/* 24 more shades of gray (does not repeat 1/8th increments) */
SetColorEntry(16, 2048, 2048, 2048); /* 1/32 gray */
SetColorEntry(17, 4096, 4096, 4096); /* 2/32 gray */
SetColorEntry(18, 6144, 6144, 6144); /* 3/32 gray */
SetColorEntry(19,10240,10240,10240); /* 5/32 gray */
SetColorEntry(20,12288,12288,12288); /* 6/32 gray */
SetColorEntry(21,14336,14336,14336); /* 7/32 gray */
SetColorEntry(22,18432,18432,18432); /* 9/32 gray */
SetColorEntry(23,20480,20480,20480); /* 10/32 gray */
SetColorEntry(24,22528,22528,22528); /* 11/32 gray */
SetColorEntry(25,26624,26624,26624); /* 13/32 gray */
SetColorEntry(26,28672,28672,28672); /* 14/32 gray */
SetColorEntry(27,30720,30720,30720); /* 15/32 gray */
SetColorEntry(28,34815,34815,34815); /* 17/32 gray */
SetColorEntry(29,36863,36863,36863); /* 18/32 gray */
SetColorEntry(30,38911,38911,38911); /* 19/32 gray */
SetColorEntry(31,43007,43007,43007); /* 21/32 gray */
SetColorEntry(32,45055,45055,45055); /* 22/32 gray */
SetColorEntry(33,47103,47103,47103); /* 23/32 gray */
SetColorEntry(34,51199,51199,51199); /* 25/32 gray */
SetColorEntry(35,53247,53247,53247); /* 26/32 gray */
SetColorEntry(36,55295,55295,55295); /* 27/32 gray */
SetColorEntry(37,59391,59391,59391); /* 29/32 gray */
SetColorEntry(38,61439,61439,61439); /* 30/32 gray */
SetColorEntry(39,63487,63487,63487); /* 31/32 gray */
/* The remainder of color table defines a color cube with six steps
for each primary color. Note that the corners of this cube repeat
previous colors,but simplifies the mapping between RGB colors and
color map indices. This color cube spans indices 40 through 255.
*/
{
int r,g,b;
for (r= 0; r < 6; r++)
for (g= 0; g < 6; g++)
for (b= 0; b < 6; b++)
{
int i= 40 + ((36 * r) + (6 * b) + g);
if (i > 255) error("index out of range in color table compuation");
SetColorEntry(i,(r * 65535) / 5,(g * 65535) / 5,(b * 65535) / 5);
}
}
if (stVisual->class == PseudoColor)
{
XSetWindowColormap(stDisplay,stWindow,stColormap);
/* initialise the black and white color values for cursor creation */
stColorWhite.red= stColorWhite.green= stColorWhite.blue= 65535;
if (XAllocColor(stDisplay,stColormap,&stColorWhite))
fprintf(stderr,"failed to find white pixel in Squeak colormap\n");
stColorBlack.red= stColorBlack.green= stColorBlack.blue= 0;
if (XAllocColor(stDisplay,stColormap,&stColorBlack))
fprintf(stderr,"failed to find black pixel in Squeak colormap\n");
setupDownGradingColors();
}
}
void SetUpWindow(char *displayName)
{
XRectangle windowBounds= { 0,0,640,480 }; /* default window bounds */
int right,bottom;
stDisplay= XOpenDisplay(displayName);
if (!stDisplay)
{
fprintf(stderr,"Could not open display '%s'.\n",displayName);
exit(1);
}
stXfd= ConnectionNumber(stDisplay);
if (savedWindowSize != 0)
{
right= windowBounds.x + ((unsigned) savedWindowSize >> 16);
bottom= windowBounds.y + (savedWindowSize & 0xFFFF);
}
else
{
right= windowBounds.x + windowBounds.width;
bottom= windowBounds.y + windowBounds.height;
}
/* minimum size is 64 x 64 */
right= ( right > (windowBounds.x + 64)) ? right : (windowBounds.x + 64);
bottom= (bottom > (windowBounds.y + 64)) ? bottom : (windowBounds.y + 64);
/* maximum bottom-right is screen bottom-right */
right= ( right <= DisplayWidth(stDisplay,DefaultScreen(stDisplay)))
? right : (DisplayWidth(stDisplay,DefaultScreen(stDisplay)) - 8);
bottom= (bottom <= DisplayHeight(stDisplay,DefaultScreen(stDisplay)))
? bottom : (DisplayHeight(stDisplay,DefaultScreen(stDisplay)) - 8);
windowBounds.width= right - windowBounds.x;
windowBounds.height= bottom - windowBounds.y;
stWindow= XCreateSimpleWindow(stDisplay,
DefaultRootWindow(stDisplay),
windowBounds.x,windowBounds.y,
windowBounds.width,windowBounds.height,
1,
BlackPixel(stDisplay,DefaultScreen(stDisplay)),
BlackPixel(stDisplay,DefaultScreen(stDisplay)));
/* accept the interesting events */
{
XSetWindowAttributes attributes;
attributes.event_mask= EVENTMASK;
attributes.backing_store= Always;
XChangeWindowAttributes(stDisplay,stWindow,
CWEventMask | CWBackingStore,
&attributes);
}
/* set the window title and resource/class names */
{
XClassHint *classHints= XAllocClassHint();
classHints->res_name= classHints->res_class= xClassName;
XSetClassHint(stDisplay,stWindow,classHints);
XStoreName(stDisplay,stWindow,shortImageName);
XFree(classHints);
}
/* tell the WM that we can't be bothered managing focus for ourselves */
{
XWMHints *wmHints= XAllocWMHints();
wmHints->input= True;
wmHints->initial_state= NormalState;
wmHints->flags= InputHint|StateHint;
XSetWMHints(stDisplay,stWindow,wmHints);
XFree((void *)wmHints);
}
/* create a suitable graphics context */
{
XGCValues gcValues;
gcValues.function= GXcopy;
gcValues.plane_mask= -1;
gcValues.subwindow_mode= IncludeInferiors;
gcValues.clip_x_origin= 0;
gcValues.clip_y_origin= 0;
gcValues.clip_mask= None;
gcValues.foreground= BlackPixel(stDisplay,DefaultScreen(stDisplay));
gcValues.background= WhitePixel(stDisplay,DefaultScreen(stDisplay));
stGC= XCreateGC(stDisplay,
stWindow,
GCFunction | GCPlaneMask | GCSubwindowMode |
GCClipXOrigin | GCClipYOrigin | GCClipMask |
GCForeground | GCBackground,
&gcValues);
}
if (noTitle || fullScreen)
/* naughty,but effective */
XSetTransientForHint(stDisplay,stWindow,DefaultRootWindow(stDisplay));
# ifdef USE_XSHM
completionType= XShmGetEventBase(stDisplay) + ShmCompletion;
# endif
}
void SetWindowSize(void)
{
int width,height,maxWidth,maxHeight;
if (savedWindowSize != 0)
{
width= (unsigned)savedWindowSize >> 16;
height= savedWindowSize & 0xFFFF;
}
else
{
width= 640;
height= 480;
}
/* minimum size is 64 x 64 */
width= ( width > 64) ? width : 64;
height= (height > 64) ? height : 64;
/* maximum size is screen size */
maxWidth= (DisplayWidth(stDisplay,DefaultScreen(stDisplay)));
maxHeight= (DisplayHeight(stDisplay,DefaultScreen(stDisplay)));
width= ( width <= maxWidth) ? width : maxWidth;
height= (height <= maxHeight) ? height : maxHeight;
if (fullScreen) {
width= maxWidth;
height= maxHeight;
}
XResizeWindow(stDisplay,stWindow,width,height);
}
/*** Event Recording Functions ***/
static int translateCode(KeySym symbolic)
{
# define ALT (8<<8)
switch (symbolic)
{
case XK_Left: return 28;
case XK_Up: return 30;
case XK_Right: return 29;
case XK_Down: return 31;
case XK_Insert: return 5;
case XK_Prior: return 11; /* page up */
case XK_Next: return 12; /* page down */
case XK_Home: return 1;
case XK_End: return 4;
/* "aliases" for Sun keyboards */
case XK_R9: return 11; /* page up */
case XK_R15: return 12; /* page down */
case XK_R7: return 1; /* home */
case XK_R13: return 4; /* end */
case XK_L1: return ALT+'.'; /* stop */
case XK_L2: return ALT+'j'; /* again */
case XK_L4: return ALT+'z'; /* undo */
case XK_L6: return ALT+'c'; /* copy */
case XK_L8: return ALT+'v'; /* paste */
case XK_L9: return ALT+'f'; /* find */
case XK_L10: return ALT+'x'; /* cut */
default: return -1;
}
/*NOTREACHED*/
# undef ALT
}
void recordKeystroke(XKeyEvent *theEvent)
{
int keystate;
unsigned char buf[32];
int nConv;
KeySym symbolic;
nConv= XLookupString(theEvent,buf,sizeof(buf),&symbolic,0);
keystate= buf[0];
if (nConv == 0 && (keystate= translateCode(symbolic)) < 0)
return; /* unknown key */
if (keystate == 127) keystate= 8; /* DEL --> BS */
keystate|= (modifierMap[(theEvent->state) & 0xF] << 8);
if (keystate == interruptKeycode)
{
/* Note: interrupt key is "meta"; it not reported as a keystroke */
interruptPending= true;
interruptCheckCounter= 0;
}
else
{
/* bug: this should be rewritten to cope with nConv > 1 */
keyBuf[keyBufPut]= keystate;
keyBufPut= (keyBufPut + 1) % KEYBUF_SIZE;
if (keyBufGet == keyBufPut)
{
/* buffer overflow; drop the last character */
keyBufGet= (keyBufGet + 1) % KEYBUF_SIZE;
keyBufOverflows++;
}
}
}
void recordMouseDown(XButtonEvent *theEvent)
{
int stButtons= 0;
switch (theEvent->button)
{
case 1: stButtons= 4; break;
case 2: stButtons= 2; break;
case 3: stButtons= 1; break;
default: ioBeep(); break;
}
if (stButtons == 4) /* red button honours the modifiers */
{
if (theEvent->state & MOD_CONTROL)
stButtons= 2; /* yellow button if CTRL down */
else if (theEvent->state & MOD_META)
stButtons= 1; /* blue button if META down */
}
/* button state: low three bits are mouse buttons; next 4 bits are modifier bits */
buttonState= (modifierMap[(theEvent->state) & 0xF] << 3) | (stButtons & 0x7);
}
/* both button and key events have the state member in the same place */
void recordModifierButtons(XButtonEvent *theEvent)
{
int stButtons= 0;
if (theEvent->type == ButtonPress)
stButtons= buttonState & 0x7;
else
stButtons= 0;
/* button state: low three bits are mouse buttons; next 4 bits are modifier bits */
buttonState= (modifierMap[(theEvent->state) & 0xF] << 3) | (stButtons & 0x7);
}
#endif !HEADLESS
/*** I/O Primitives ***/
int ioFormPrint(int bitsAddr,int width,int height,int depth,
double hScale,double vScale,int landscapeFlag)
{
#ifdef HEADLESS
fprintf(stderr,
"Sorry,a headless VM cannot print Forms. If you\n"
"*really* need this then let me know,since there\n"
"is a (rather painful to implement) solution.\n");
return false;
#else !HEADLESS
/* Write the form as a PPM (Portable PixMap) file,from which it can
be converted into almost any existing graphical format (including
PostScript). See the "netpbm" utilities for a huge collection of
image manipulation tools that understand the PPM format.
Note that "xv" can also read,convert,and do image processing on
PPM files.
The output filename is defined in "sqPlatformSpecific.h". */
FILE *ppm;
int ok= true;
if ((ppm= fopen(SQ_FORM_FILENAME,"wb")) == 0) return false;
/* PPM magic number and pixmap header */
fprintf(ppm,"P3\n%d %d 65535\n",width,height);
switch (depth) {
case 8: {
unsigned char *bits= (unsigned char *) bitsAddr;
int ppw= 32 / depth;
int raster= ((width + ppw - 1) / ppw) * 4;
/* stColors[] is too approximate: query the real colormap */
XColor colors[256];
int i;
for (i= 0; i < 256; ++i) colors[i].pixel= i;
/* all colors in one query reduces server traffic */
XQueryColors(stDisplay,stColormap,colors,256);
/* write the pixmap */
{
int y;
for (y= 0; y < height; ++y) {
int x;
for (x= 0; x < width; ++x) {
/* everything is backwards (as usual ;) */
int index= y * raster + x;
int byte= 3 - (index & 0x00000003);
int word= index & -4;
int pixel= bits[word + byte];
fprintf(ppm,"%d %d %d\n",
colors[pixel].red,colors[pixel].green,colors[pixel].blue);
}
}
}
break;
} /* case 8 */
default:
fprintf(stderr,
"Depth %d pixmaps are not yet supported. If you *really*\n"
"need this then bribe me with something (a 24-bit Macintosh\n"
"PCI video card would certainly do the trick ;).\n");
ok= false;
break;
} /* switch */
fclose(ppm);
return ok;
#endif !HEADLESS
}
int ioBeep(void)
{
#ifndef HEADLESS
XBell(stDisplay,0); /* ring at default volume */
#endif
return 0;
}
int ioGetButtonState(void)
{
ioProcessEvents(); /* process all pending events */
#ifndef HEADLESS
return buttonState;
#else
return 0;
#endif
}
int ioGetKeystroke(void)
{
int keystate;
ioProcessEvents(); /* process all pending events */
#ifdef HEADLESS
return -1; /* keystroke buffer is empty */
#else
if (keyBufGet == keyBufPut)
return -1; /* keystroke buffer is empty */
keystate= keyBuf[keyBufGet];
keyBufGet= (keyBufGet + 1) % KEYBUF_SIZE;
/* set modifer bits in buttonState to reflect the last keystroke fetched */
buttonState= ((keystate >> 5) & 0xF8) | (buttonState & 0x7);
return keystate;
#endif
}
int ioRelinquishProcessorForMicroseconds(int microSeconds)
{
/* sleep in select() for immediate response to socket i/o */
#ifdef HEADLESS
aioPollForIO(microSeconds,0);
#else
aioPollForIO(microSeconds,stXfd);
#endif
return microSeconds;
}
int ioPeekKeystroke(void)
{
#ifdef HEADLESS
ioProcessEvents(); /* process all pending events */
return -1; /* keystroke buffer is empty */
#else
int keystate;
ioProcessEvents(); /* process all pending events */
if (keyBufGet == keyBufPut)
return -1; /* keystroke buffer is empty */
keystate= keyBuf[keyBufGet];
/* set modifer bits in buttonState to reflect the last keystroke peeked at */
buttonState= ((keystate >> 5) & 0xF8) | (buttonState & 0x7);
return keystate;
#endif
}
/* this should be rewritten to use SIGIO and/or the interval timers */
int ioProcessEvents(void)
{
static unsigned long nextPollTick= 0;
if ((unsigned long)ioMSecs() > nextPollTick)
{
/* time to process events! */
while (HandleEvents())
{
/* process all pending events */
}
/* wait a while before trying again */
nextPollTick= ioMSecs() + (1000 / MAXPOLLSPERSEC);
}
return 0;
}
int ioSetFullScreen(int fullScreen)
{
#ifndef HEADLESS
int winX,winY,winW,winH,winB,scrW,scrH;
/* get screen size */
scrW= (DisplayWidth(stDisplay,DefaultScreen(stDisplay)));
scrH= (DisplayHeight(stDisplay,DefaultScreen(stDisplay)));
if (fullScreen) {
/* setting full-screen mode */
if (savedWindowOrigin == -1) {
/* EITHER: no previous call,OR: previous call disabled full-screen mode */
{
/* current origin and extent of Squeak window */
Window root;
int depth;
XGetGeometry(stDisplay,stWindow,&root,
&winX,&winY,&winW,&winH,&winB,&depth);
}
/* width must be a multiple of sizeof(void *),or X[Shm]PutImage goes gaga */
if ((winW % sizeof(void *)) != 0)
winW= (winW / sizeof(void *)) * sizeof(void *);
savedWindowSize= (winW << 16) + (winH & 0xFFFF);
savedWindowOrigin= (winX << 16) + (winY & 0xFFFF);
if ((scrW % sizeof(void *)) != 0)
scrW= (scrW / sizeof(void *)) * sizeof(void *);
XMoveResizeWindow(stDisplay,stWindow,0,0,scrW,scrH);
/* sync avoids race with ioScreenSize() reading geometry before resize event */
XSync(stDisplay,False);
}
} else {
/* reverting to sub-screen mode */
if (savedWindowOrigin != -1) { /* previous call enabled full-screen mode */
/* get old window size */
winW= (unsigned) savedWindowSize >> 16;
winH= savedWindowSize & 0xFFFF;
/* minimum size is 64 x 64 */
winW= (winW > 64) ? winW : 64;
winH= (winH > 64) ? winH : 64;
/* old origin */
winX= savedWindowOrigin >> 16;
winY= savedWindowOrigin & 0xFFFF;
savedWindowOrigin= -1; /* prevents consecutive full-screen disables */
XMoveResizeWindow(stDisplay,stWindow,winX,winY,winW,winH);
/* sync avoids race with ioScreenSize() reading geometry before resize event */
XSync(stDisplay,False);
}
}
#endif !HEADLESS
return 0;
}
#ifndef HEADLESS
/* shared-memory stuff */
static void *stMalloc(size_t lbs)
{
#ifdef USE_XSHM
if (!useXshm)
#endif
return (void *)malloc(lbs);
#ifdef USE_XSHM
if ((stShmInfo.shmid= shmget(IPC_PRIVATE,lbs,IPC_CREAT|0777)) == -1) {
perror("shmget");
exit(1);
}
if ((int)(stShmInfo.shmaddr= (char *)shmat(stShmInfo.shmident,0,0)) == -1) {
perror("shmat");
exit(1);
}
stShmInfo.readOnly= False;
if (!XShmAttach(stDisplay,&stShmInfo)) {
fprintf(stderr,"XShmAttach: operation failed\n");
abort();
}
return stShmInfo.shmaddr;
#endif
}
static void stFree(void *addr)
{
#ifdef USE_XSHM
if (!useXshm)
#endif
{
free(addr);
return;
}
#ifdef USE_XSHM
shmctl(stShmInfo.shmident,IPC_RMident,0);
shmdt(stShmInfo.shmaddr);
#endif
}
#ifdef USE_XSHM
static void shmExit(void)
{
if (stDisplayBitmap && useXshm)
stFree(stDisplayBitmap);
}
#endif
static XImage *stXCreateImage(Display *display,Visual *visual,
int depth,int format,int flags,char *data,
int width,int height,int bpp,int pad)
{
#ifdef USE_XSHM
if (!useXshm)
#endif
return XCreateImage(display,visual,depth,format,flags,
data,width,height,bpp,pad);
#ifdef USE_XSHM
return XShmCreateImage(display,visual,depth,format,data,
&stShmInfo,width,height);
#endif
}
static void stXPutImage(Display *display,Window window,GC gc,XImage *image,
int src_x,int src_y,int dst_x,int dst_y,int w,int h)
{
#ifdef USE_XSHM
if (!useXshm)
#endif
{
XPutImage(display,window,gc,image,src_x,src_y,dst_x,dst_y,w,h);
return;
}
#ifdef USE_XSHM
XShmPutImage(display,window,gc,image,src_x,src_y,dst_x,dst_y,w,h,True);
++completions;
if (!asyncUpdate)
do {
HandleEvents();
} while (completions);
#endif
}
static void stXDestroyImage(XImage *image)
{
#ifdef USE_XSHM
if (useXshm)
XShmDetach(stDisplay,&stShmInfo);
#endif
XDestroyImage(image);
}
#define bytesPerLine(width,depth) ((((width)*(depth) + 31) >> 5) << 2)
#define bytesPerLineRD(width,depth) ((((width)*(depth)) >> 5) << 2)
#endif !HEADLESS
int ioForceDisplayUpdate(void)
{
#if !defined(HEADLESS) && defined(USE_XSHM)
if (asyncUpdate) {
XFlush(stDisplay);
do {
HandleEvents();
} while (completions);
}
#endif
return 0;
}
int ioShowDisplay(int dispBitsIndex,int width,int height,int depth,
int affectedL,int affectedR,int affectedT,int affectedB)
{
#ifndef HEADLESS
if (stWindow == 0)
return 0;
if(affectedR <= affectedL || affectedT >= affectedB)
return 1;
if (!(depth == 8 || depth == 16 || depth == 32))
{
fprintf(stderr,"depth %d is not supported\n",depth);
exit(1);
return 0;
}
if (stDisplayBitsIndex != dispBitsIndex)
{
#if defined(USE_XSHM)
if (asyncUpdate) {
/* wait for pending updates to complete before freeing the XImage */
while (completions) HandleEvents();
}
#endif
stDisplayBitsIndex= dispBitsIndex;
if (stImage)
{
stImage->data= 0; /* don't you dare free() Display's Bitmap! */
stXDestroyImage(stImage);
if (stDisplayBitmap)
{
stFree(stDisplayBitmap);
stDisplayBitmap = 0;
}
}
#ifndef USE_XSHM
# define useXshm 0
#endif
#ifdef HAS_LSB_FIRST
if (!useXshm && depth == stBitsPerPixel && depth == 32 && stHasSameRGBMask32)
#else
if (!useXshm && depth == stBitsPerPixel &&
(depth != 16 || stHasSameRGBMask16) &&
(depth != 32 || stHasSameRGBMask32))
#endif
{
stDisplayBitmap= 0;
}
else
{
stDisplayBitmap= stMalloc(bytesPerLine(width,stBitsPerPixel) * height);
}
#ifndef USE_XSHM
# undef useXshm
#endif
stImage= stXCreateImage(stDisplay,
DefaultVisual(stDisplay,DefaultScreen(stDisplay)),
stDepth,
ZPixmap,
0,
(stDisplayBitmap
? stDisplayBitmap
: (char *)stDisplayBitsIndex),
width,
height,
32,
0);
/* Xlib ignores the following */
#ifdef HAS_LSB_FIRST
stImage->byte_order = LSBFirst;
stImage->bitmap_bit_order = LSBFirst;
#else
stImage->byte_order = MSBFirst;
stImage->bitmap_bit_order = MSBFirst;
#endif
/* not really required (since we never call Get/PutPixel),but what the hey */
/*
if (!XInitImage(stImage))
fprintf(stderr,"XInitImage failed (but we don't care)\n");
*/
}
/* this can happen after resizing the window */
if (affectedR > width) affectedR= width;
if (affectedB > height) affectedB= height;
if (depth != stBitsPerPixel)
{
if (depth == 8)
{
if (stBitsPerPixel == 16)
{
copyImage8To16((int *)dispBitsIndex,(int *)stDisplayBitmap,
width,height,
affectedL,affectedT,affectedR,affectedB);
}
else /* stBitsPerPixel == 32 */
{
copyImage8To32((int *)dispBitsIndex,(int *)stDisplayBitmap,
width,height,
affectedL,affectedT,affectedR,affectedB);
}
}
else if (depth == 16)
{
if (stBitsPerPixel == 8)
{
copyImage16To8((int *)dispBitsIndex,(int *)stDisplayBitmap,
width,height,
affectedL,affectedT,affectedR,affectedB);
}
else /* stBitsPerPixel == 32 */
{
copyImage16To32((int *)dispBitsIndex,(int *)stDisplayBitmap,
width,height,
affectedL,affectedT,affectedR,affectedB);
}
}
else /* depth == 32 */
{
if (stBitsPerPixel == 8)
{
copyImage32To8((int *)dispBitsIndex,(int *)stDisplayBitmap,
width,height,
affectedL,affectedT,affectedR,affectedB);
}
else /* stBitsPerPixel == 16 */
{
copyImage32To16((int *)dispBitsIndex,(int *)stDisplayBitmap,
width,height,
affectedL,affectedT,affectedR,affectedB);
}
}
}
else /* depth == stBitsPerPixel */
{
if (depth == 16 && !stHasSameRGBMask16)
{
copyImage16To16((int *)dispBitsIndex,(int *)stDisplayBitmap,
width,height,
affectedL,affectedT,affectedR,affectedB);
}
else if (depth == 32 && !stHasSameRGBMask32)
{
copyImage32To32((int *)dispBitsIndex,(int *)stDisplayBitmap,
width,height,
affectedL,affectedT,affectedR,affectedB);
}
#ifdef HAS_LSB_FIRST
else if (depth == 8)
{
copyReverseImageBytes((int *)dispBitsIndex,(int *)stDisplayBitmap,
depth,width,height,
affectedL,affectedT,affectedR,affectedB);
}
else if (depth == 16)
{
copyReverseImageWords((int *)dispBitsIndex,(int *)stDisplayBitmap,
depth,width,height,
affectedL,affectedT,affectedR,affectedB);
}
#else
# ifdef USE_XSHM
else if (useXshm) {
if (depth == 8) {
copyImage8To8((int *)dispBitsIndex,(int *)stDisplayBitmap,
width,height,affectedL,affectedT,affectedR,affectedB);
} else {
fprintf(stderr,"shared memory not supported for this depth/byte-order\n");
exit(1);
}
}
# endif
#endif
}
stXPutImage(stDisplay,stWindow,stGC,stImage,
affectedL,affectedT, /* src_x,src_y */
affectedL,affectedT, /* dst_x,dst_y */
affectedR-affectedL, /* width */
affectedB-affectedT); /* height */
#endif
return 0;
}
#ifndef HEADLESS
void copyReverseImageBytes(int *fromImageData,int *toImageData,
int depth,int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB)
{
register int scanLine,firstWord,lastWord;
register int line;
scanLine= bytesPerLine(width,depth);
firstWord= scanLine*affectedT + bytesPerLineRD(affectedL,depth);
lastWord= scanLine*affectedT + bytesPerLine(affectedR,depth);
for (line= affectedT; line < affectedB; line++)
{
register unsigned char *from= (unsigned char *)((int)fromImageData+firstWord);
register unsigned char *limit= (unsigned char *)((int)fromImageData+lastWord);
register unsigned char *to= (unsigned char *)((int)toImageData+firstWord);
while (from < limit)
{
to[0]= from[3];
to[1]= from[2];
to[2]= from[1];
to[3]= from[0];
from+= 4;
to+= 4;
}
firstWord+= scanLine;
lastWord+= scanLine;
}
}
void copyReverseImageWords(int *fromImageData,int *toImageData,
int depth,int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB)
{
register int scanLine,firstWord,lastWord;
register int line;
scanLine= bytesPerLine(width,depth);
firstWord= scanLine*affectedT + bytesPerLineRD(affectedL,depth);
lastWord= scanLine*affectedT + bytesPerLine(affectedR,depth);
for (line= affectedT; line < affectedB; line++)
{
register unsigned short *from= (unsigned short *)((int)fromImageData+firstWord);
register unsigned short *limit= (unsigned short *)((int)fromImageData+lastWord);
register unsigned short *to= (unsigned short *)((int)toImageData+firstWord);
while (from < limit)
{
to[0]= from[1];
to[1]= from[0];
from+= 2;
to+= 2;
}
firstWord+= scanLine;
lastWord+= scanLine;
}
}
void copyImage8To8(int *fromImageData,int *toImageData,
int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB)
{
register int scanLine,firstWord,lastWord;
register int line;
scanLine= bytesPerLine(width,8);
firstWord= scanLine*affectedT + bytesPerLineRD(affectedL,8);
lastWord= scanLine*affectedT + bytesPerLine(affectedR,8);
for (line= affectedT; line < affectedB; line++) {
register unsigned int *from= (unsigned int *)((int)fromImageData+firstWord);
register unsigned int *limit= (unsigned int *)((int)fromImageData+lastWord);
register unsigned int *to= (unsigned int *)((int)toImageData+firstWord);
while (from < limit)
*to++= *from++;
firstWord+= scanLine;
lastWord+= scanLine;
}
}
void copyImage8To16(int *fromImageData,int *toImageData,
int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB)
{
int scanLine8,firstWord8,lastWord8;
int scanLine16,firstWord16,lastWord16;
register int line;
scanLine8= bytesPerLine(width,8);
firstWord8= scanLine8*affectedT + bytesPerLineRD(affectedL,8);
lastWord8= scanLine8*affectedT + bytesPerLine(affectedR,8);
scanLine16= bytesPerLine(width,16);
firstWord16= scanLine16*affectedT + (bytesPerLineRD(affectedL,8) << 1);
lastWord16= scanLine16*affectedT + (bytesPerLine(affectedR,8) << 1);
for (line= affectedT; line < affectedB; line++)
{
register unsigned char *from= (unsigned char *)((int)fromImageData+firstWord8);
register unsigned char *limit= (unsigned char *)((int)fromImageData+lastWord8);
register unsigned short *to= (unsigned short *)((int)toImageData+firstWord16);
while (from < limit)
{
#ifdef HAS_LSB_FIRST
to[0]= stColors[from[3]];
to[1]= stColors[from[2]];
to[2]= stColors[from[1]];
to[3]= stColors[from[0]];
#else
to[0]= stColors[from[0]];
to[1]= stColors[from[1]];
to[2]= stColors[from[2]];
to[3]= stColors[from[3]];
#endif
from+= 4;
to+= 4;
}
firstWord8+= scanLine8;
lastWord8+= scanLine8;
firstWord16+= scanLine16;
lastWord16+= scanLine16;
}
}
void copyImage16To8(int *fromImageData,int *toImageData,
int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB)
{
int scanLine16,firstWord16,lastWord16;
int scanLine8,firstWord8,lastWord8;
int line;
#define map16To8(w) (col= (w),stDownGradingColors[ \
(((col >> (10+(5-3))) & 0x7) << 5) | \
(((col >> (5+(5-3))) & 0x7) << 2) | \
((col >> (0+(5-2))) & 0x7)])
scanLine16= bytesPerLine(width,16);
firstWord16= scanLine16*affectedT + bytesPerLineRD(affectedL,16);
lastWord16= scanLine16*affectedT + bytesPerLine(affectedR,16);
scanLine8= bytesPerLine(width,8);
firstWord8= scanLine8*affectedT + (bytesPerLineRD(affectedL,16) >> 1);
lastWord8= scanLine8*affectedT + (bytesPerLine(affectedR,16) >> 1);
for (line= affectedT; line < affectedB; line++)
{
register int col;
register unsigned short *from= (unsigned short *)((int)fromImageData+firstWord16);
register unsigned short *limit= (unsigned short *)((int)fromImageData+lastWord16);
register unsigned char *to= (unsigned char *)((int)toImageData+firstWord8);
while (from < limit)
{
#ifdef HAS_LSB_FIRST
to[0]= map16To8(from[1]);
to[1]= map16To8(from[0]);
#else
to[0]= map16To8(from[0]);
to[1]= map16To8(from[1]);
#endif
from+= 2;
to+= 2;
}
firstWord16+= scanLine16;
lastWord16+= scanLine16;
firstWord8+= scanLine8;
lastWord8+= scanLine8;
}
#undef map16To8
}
void copyImage8To32(int *fromImageData,int *toImageData,
int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB)
{
int scanLine8,firstWord8,lastWord8;
int scanLine32,firstWord32,lastWord32;
int line;
scanLine8= bytesPerLine(width,8);
firstWord8= scanLine8*affectedT + bytesPerLineRD(affectedL,8);
lastWord8= scanLine8*affectedT + bytesPerLine(affectedR,8);
scanLine32= bytesPerLine(width,32);
firstWord32= scanLine32*affectedT + (bytesPerLineRD(affectedL,8) << 2);
lastWord32= scanLine32*affectedT + (bytesPerLine(affectedR,8) << 2);
for (line= affectedT; line < affectedB; line++)
{
register unsigned char *from= (unsigned char *)((int)fromImageData+firstWord8);
register unsigned char *limit= (unsigned char *)((int)fromImageData+lastWord8);
register unsigned int *to= (unsigned int *)((int)toImageData+firstWord32);
while (from < limit)
{
#ifdef HAS_LSB_FIRST
to[0]= stColors[from[3]];
to[1]= stColors[from[2]];
to[2]= stColors[from[1]];
to[3]= stColors[from[0]];
#else
to[0]= stColors[from[0]];
to[1]= stColors[from[1]];
to[2]= stColors[from[2]];
to[3]= stColors[from[3]];
#endif
from+= 4;
to+= 4;
}
firstWord8+= scanLine8;
lastWord8+= scanLine8;
firstWord32+= scanLine32;
lastWord32+= scanLine32;
}
}
void copyImage32To8(int *fromImageData,int *toImageData,
int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB)
{
int scanLine32,firstWord32,lastWord32;
int scanLine8,firstWord8,lastWord8;
int line;
#define map32To8(w) (col= (w),stDownGradingColors[\
(((col >> (16+(8-3))) & 0x7) << 5) | \
(((col >> (8+(8-3))) & 0x7) << 2) | \
((col >> (0+(8-2))) & 0x7)])
scanLine32= bytesPerLine(width,32);
firstWord32= scanLine32*affectedT + bytesPerLineRD(affectedL,32);
lastWord32= scanLine32*affectedT + bytesPerLine(affectedR,32);
scanLine8= bytesPerLine(width,8);
firstWord8= scanLine8*affectedT + (bytesPerLineRD(affectedL,32) >> 2);
lastWord8= scanLine8*affectedT + (bytesPerLine(affectedR,32) >> 2);
for (line= affectedT; line < affectedB; line++)
{
register int col;
register unsigned int *from= (unsigned int *)((int)fromImageData+firstWord32);
register unsigned int *limit= (unsigned int *)((int)fromImageData+lastWord32);
register unsigned char *to= (unsigned char *)((int)toImageData+firstWord8);
while (from < limit)
{
to[0]= map32To8(from[0]);
from++;
to++;
}
firstWord32+= scanLine32;
lastWord32+= scanLine32;
firstWord8+= scanLine8;
lastWord8+= scanLine8;
}
#undef map32To8
}
void copyImage16To32(int *fromImageData,int *toImageData,
int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB)
{
int scanLine16,firstWord16,lastWord16;
int scanLine32,firstWord32,lastWord32;
int line;
int rshift,gshift,bshift;
register unsigned int col;
rshift= stRNMask-5 + stRShift;
gshift= stGNMask-5 + stGShift;
bshift= stBNMask-5 + stBShift;
#define map16To32(w) (col = (w),\
(((col >> 10) & 0x1f) << rshift) | \
(((col >> 5) & 0x1f) << gshift) | \
((col & 0x1f) << bshift))
scanLine16= bytesPerLine(width,16);
firstWord16= scanLine16*affectedT + bytesPerLineRD(affectedL,16);
lastWord16= scanLine16*affectedT + bytesPerLine(affectedR,16);
scanLine32= bytesPerLine(width,32);
firstWord32= scanLine32*affectedT + (bytesPerLineRD(affectedL,16) << 1);
lastWord32= scanLine32*affectedT + (bytesPerLine(affectedR,16) << 1);
for (line= affectedT; line < affectedB; line++)
{
register unsigned short *from= (unsigned short *)((int)fromImageData+firstWord16);
register unsigned short *limit= (unsigned short *)((int)fromImageData+lastWord16);
register unsigned int *to= (unsigned int *)((int)toImageData+firstWord32);
while (from < limit)
{
#ifdef HAS_LSB_FIRST
to[0]= map16To32(from[1]);
to[1]= map16To32(from[0]);
#else
to[0]= map16To32(from[0]);
to[1]= map16To32(from[1]);
#endif
from+= 2;
to+= 2;
}
firstWord16+= scanLine16;
lastWord16+= scanLine16;
firstWord32+= scanLine32;
lastWord32+= scanLine32;
}
#undef map16To32
}
void copyImage32To16(int *fromImageData,int *toImageData,
int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB)
{
int scanLine32,firstWord32,lastWord32;
int scanLine16,firstWord16,lastWord16;
int line;
int rshift,gshift,bshift;
register unsigned int col;
rshift= stRNMask-5 + stRShift;
gshift= stGNMask-5 + stGShift;
bshift= stBNMask-5 + stBShift;
#define map32To16(w) (col = (w),\
(((col >> 16) & 0xff) << rshift) | \
(((col >> 8) & 0xff) << gshift) | \
((col & 0xff) << bshift))
scanLine32= bytesPerLine(width,32);
firstWord32= scanLine32*affectedT + bytesPerLineRD(affectedL,32);
lastWord32= scanLine32*affectedT + bytesPerLine(affectedR,32);
scanLine16= bytesPerLine(width,16);
firstWord16= scanLine16*affectedT + (bytesPerLineRD(affectedL,32) >> 1);
lastWord16= scanLine16*affectedT + (bytesPerLine(affectedR,32) >> 1);
for (line= affectedT; line < affectedB; line++)
{
register unsigned int *from= (unsigned int *)((int)fromImageData+firstWord32);
register unsigned int *limit= (unsigned int *)((int)fromImageData+lastWord32);
register unsigned short *to= (unsigned short *)((int)toImageData+firstWord16);
while (from < limit)
{
to[0]= map32To16(from[1]);
from++;
to++;
}
firstWord32+= scanLine32;
lastWord32+= scanLine32;
firstWord16+= scanLine16;
lastWord16+= scanLine16;
}
#undef map32To16
}
void copyImage16To16(int *fromImageData,int *toImageData,
int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB)
{
int scanLine16,firstWord16,lastWord16;
int line;
int rshift,gshift,bshift;
register unsigned int col;
rshift= stRNMask-5 + stRShift;
gshift= stGNMask-5 + stGShift;
bshift= stBNMask-5 + stBShift;
#define map16To16(w) (col = (w),\
(((col >> 10) & 0x1f) << rshift) | \
(((col >> 5) & 0x1f) << gshift) | \
((col & 0x1f) << bshift))
scanLine16= bytesPerLine(width,16);
firstWord16= scanLine16*affectedT + bytesPerLineRD(affectedL,16);
lastWord16= scanLine16*affectedT + bytesPerLine(affectedR,16);
for (line= affectedT; line < affectedB; line++)
{
register unsigned short *from= (unsigned short *)((int)fromImageData+firstWord16);
register unsigned short *limit= (unsigned short *)((int)fromImageData+lastWord16);
register unsigned short *to= (unsigned short *)((int)toImageData+firstWord16);
while (from < limit)
{
#ifdef HAS_LSB_FIRST
to[0]= map16To16(from[1]);
to[1]= map16To16(from[0]);
#else
to[0]= map16To16(from[0]);
to[1]= map16To16(from[1]);
#endif
from+= 2;
to+= 2;
}
firstWord16+= scanLine16;
lastWord16+= scanLine16;
}
#undef map16To16
}
void copyImage32To32(int *fromImageData,int *toImageData,
int width,int height,
int affectedL,int affectedT,int affectedR,int affectedB)
{
int scanLine32,firstWord32,lastWord32;
int line;
int rshift,gshift,bshift;
register unsigned int col;
rshift= stRNMask-8 + stRShift;
gshift= stGNMask-8 + stGShift;
bshift= stBNMask-8 + stBShift;
#define map32To32(w) (col = (w),\
(((col >> 16) & 0xff) << rshift) | \
(((col >> 8) & 0xff) << gshift) | \
((col & 0xff) << bshift))
scanLine32= bytesPerLine(width,32);
firstWord32= scanLine32*affectedT + bytesPerLineRD(affectedL,32);
lastWord32= scanLine32*affectedT + bytesPerLine(affectedR,32);
for (line= affectedT; line < affectedB; line++)
{
register unsigned int *from= (unsigned int *)((int)fromImageData+firstWord32);
register unsigned int *limit= (unsigned int *)((int)fromImageData+lastWord32);
register unsigned int *to= (unsigned int *)((int)toImageData+firstWord32);
while (from < limit)
{
*to= map32To32(*from);
from++;
to++;
}
firstWord32+= scanLine32;
lastWord32+= scanLine32;
}
#undef map32To32
}
#endif
/*** Image File Naming ***/
void RecordFullPathForImageName(char *localImageName)
{
int i;
/* get canonical path to image */
if (!realpath(localImageName,vmPath))
imageNotFound(localImageName);
strcpy(imageName,vmPath);
/* truncate vmPath to dirname */
for (i= strlen(vmPath); i >= 0; i--)
if ('/' == vmPath[i])
{
vmPath[i+1]= '\0';
return;
}
/* this might just work in an emergency... */
strcpy(imageName,vmPath);
}
/*** Timing support ***/
void SetUpTimers(void)
{
gettimeofday(&startUpTime,0);
}
101
/*** Command line ***/
static char *progName;
void usage()
{
printf("Usage: %s [<options>] [<imageName>]\n\n",progName);
printf("<options> are:\n");
printf(" -display <dpy> display on <dpy> (default: $DISPLAY)\n");
#ifdef USE_XSHM
printf(" -xshm enable X shared memory extensions\n");
#endif
printf(" -notitle turn off the Squeak window title bar\n");
printf(" -fullscreen occupy the entire screen\n");
printf(" -lazy go to sleep when main window unmapped\n");
printf(" -memory <size>[mk] set initial memory size (default: 5m)\n");
#ifdef CCACHE
printf(" -ccache <size> set context cache size (default: 16)\n");
#endif
printf(" -version print version information,then exit\n");
printf("\nNotes:\n");
printf(" <imageName> defaults to 'squeak.image'.\n");
printf(" Using 'unix:0' for <dpy> may improve local display performance.\n");
printf(" -xshm only works when Squeak is running on the X server host.\n");
exit(1);
}
void imageNotFound(char *imageName)
{
/* image file is not found */
fprintf(stderr,"Could not open the Squeak image file '%s'.\n\n",imageName);
fprintf(stderr,"There are two ways to open a Squeak image file. You can:\n");
fprintf(stderr," 1. Put the name of the image file on the command line\n");
fprintf(stderr," when you run Squeak (use '-help' for more information).\n");
fprintf(stderr," 2. Save an image (from inside Squeak) with the name 'clone'\n");
fprintf(stderr," and run Squeak from the directory containing it.\n");
exit(1);
}
int strtobkm(char *str) {
char *suffix;
int value= strtol(str,&suffix,10);
switch (*suffix) {
case 'k': case 'K':
value*= 1024;
break;
case 'm': case 'M':
value*= 1024*1024;
break;
}
return value;
}
void ParseArguments(int argc,char **argv)
{
char *ev;
initialArgv= argv;
initialArgc= 0;
/* defaults */
if ((ev= getenv("SQUEAK_IMAGE")))
strcpy(shortImageName,ev);
else
strcpy(shortImageName,"squeak.image");
if ((ev= getenv("SQUEAK_MEMORY")))
initialHeapSize= strtobkm(ev);
else
initialHeapSize= 5*1024*1024; /* 5 megabytes by default */
if (getenv("SQUEAK_LAZY"))
sleepWhenUnmapped= 1;
else
sleepWhenUnmapped= 0;
if (getenv("SQUEAK_NOTITLE"))
noTitle= 1;
else
noTitle= 0;
if (getenv("SQUEAK_FULLSCREEN"))
fullScreen= 1;
else
fullScreen= 0;
#if defined(USE_XSHM) && !defined(HEADLESS)
if (getenv("SQUEAK_XSHM"))
useXshm= 1;
else
useXshm= 0;
if (getenv("SQUEAK_XASYNC"))
asyncUpdate= 1;
else
asyncUpdate= 0;
#endif
#ifdef CCACHE
if (ev= getenv("SQUEAK_CCACHE"))
stackCacheEntries= atoi(ev);
else
stackCacheEntries= 0;
contextCacheEntries= stackCacheEntries;
#endif
argc--;
argv++; /* skip VM name */
while (argc && **argv == '-') /* more options to parse */
{
if (!strcmp(*argv,"-help"))
usage();
#ifndef HEADLESS
if (!strcmp(*argv,"-display"))
{
argc--; /* skip -display */
argv++;
if (!argc) usage();
displayName= *argv++;
argc--;
continue;
}
#endif
if (!strcmp(*argv,"-memory"))
{
argc--; /* skip -memory */
argv++;
if (!argc) usage();
initialHeapSize= strtobkm(*argv++);
argc--;
continue;
}
#ifdef CCACHE
if (!strcmp(*argv,"-ccache"))
{
argc--; /* skip -ccache */
argv++;
if (!argc) usage();
stackCacheEntries= contextCacheEntries= atoi(*argv++);
argc--;
if (contextCacheEntries < 2)
{
fprintf(stderr,"context cache size must be at least 2\n");
exit(1);
}
continue;
}
#endif
#if defined(USE_XSHM) && !defined(HEADLESS)
if (!strcmp(*argv,"-xshm"))
{
argc--; /* skip -xshm */
argv++;
useXshm= 1;
continue;
}
if (!strcmp(*argv,"-xasync"))
{
argc--; /* skip -xasync */
argv++;
asyncUpdate= 1;
continue;
}
#endif
if (!strcmp(*argv,"-lazy"))
{
argc--; /* skip -lazy */
argv++;
sleepWhenUnmapped= 1;
continue;
}
if (!strcmp(*argv,"-notitle"))
{
argc--; /* skip -notitle */
argv++;
noTitle= 1;
continue;
}
if (!strcmp(*argv,"-fullscreen"))
{
argc--; /* skip -fullscreen */
argv++;
fullScreen= 1;
continue;
}
if (!strcmp(*argv,"-version"))
{
extern int vm_serial;
extern char *vm_date,*vm_version,*cc_version,*ux_version;
extern char *up_version;
fprintf(stderr,"%s/%d #%d %s%s %s\n%s\n%s\n",
vm_version,CURRENT_VERSION,vm_serial,
#ifdef USE_XSHM
"XShm ",
#else
" ",
#endif
vm_date,cc_version,ux_version,up_version);
exit(0);
}
/* assume the argument is meant for Squeak,and silently ignore it */
initialArgv[initialArgc++]= *argv++;
--argc;
}
if (argc)
{
strcpy(shortImageName,*argv);
initialArgv[initialArgc++]= *argv++;
--argc;
}
initialArgv[initialArgc]= (char *)0;
}
/*** Segmentation fault handler ***/
#include <signal.h>
void segv(int ignore)
{
error("Segmentation fault");
}
#ifdef __alpha__
/* headers for setsysinfo (see below) */
# include <sys/sysinfo.h>
# include <sys/proc.h>
#endif
int main(int argc,char **argv)
{
signal(SIGSEGV,segv);
/* initialisation */
#ifdef __alpha__
/* disable printing of unaligned access exceptions */
{
int buf[2]= { SSIN_UACPROC,UAC_NOPRINT };
if (setsysinfo(SSI_NVPAIRS,buf,1,0,0,0) < 0) {
perror("setsysinfo(UAC_NOPRINT)");
}
}
#endif
progName= argv[0];
ParseArguments(argc,argv);
SetUpTimers();
#ifndef HEADLESS
# ifdef USE_XSHM
# ifdef HAS_ON_EXIT
on_exit(shmExit);
# else
atexit(shmExit);
# endif
# endif
#endif
sqFileInit();
joystickInit();
#ifdef NEED_TZSET
tzset(); /* should _not_ be necessary! */
#endif
RecordFullPathForImageName(shortImageName);
/* check the interpreter's size assumptions for basic data types */
if (sizeof(int) != 4) error("This C compiler's integers are not 32 bits.");
if (sizeof(double) != 8) error("This C compiler's floats are not 64 bits.");
if (sizeof(time_t) != 4) error("This C compiler's time_t's are not 32 bits.");
/* read the image file and allocate memory for Squeak heap */
{
FILE *f= fopen(imageName,"r");
if (f == NULL)
imageNotFound(imageName);
readImageFromFileHeapSize(f,initialHeapSize);
fclose(f);
}
#ifndef HEADLESS
/* open the Squeak window. */
SetUpClipboard();
SetUpWindow(displayName);
SetUpPixmap();
SetWindowSize();
XMapWindow(stDisplay,stWindow);
#endif
/* run Squeak */
interpret();
return 0;
}
#endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.