NeXTWorkstation.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Sat, 02 Feb 2019 01:04:01 +0000
branchjv
changeset 8623 b8c81b323931
parent 6528 62c1dbef0b84
permissions -rw-r--r--
Merge

"{ Package: 'stx:libview' }"

DeviceWorkstation subclass:#NeXTWorkstation
	instanceVariableNames:'buffered knownDrawableIds'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-Graphics'
!

NeXTWorkstation comment:'

COPYRIGHT (c) 1992 by Claus Gittinger
	      All Rights Reserved

this class provides the interface to NeXTStep; since we cannot include
objc-code here (due to define conflicts with Class, nil ...) we call
helper functions to do the job; the helpers are in ../librun/NXsupport.c

All non-monochrome stuff is untested (I only have a monochroome station)

$Header: /cvs/stx/stx/libview/NeXTWorkstation.st,v 1.22 2013-05-21 20:49:14 cg Exp $
written spring 92 by claus
'
!

!NeXTWorkstation primitiveDefinitions!
%{

#include <stdio.h>
#include <dpsclient/wraps.h>
#include <dpsclient/psops.h>

%}
! !

!NeXTWorkstation primitiveFunctions!
%{
/*
 * cannot include objc stuff - too many name conflicts
 */
#define id INT
static INT lastDrawable = 0;

setDrawable(drawableId)
    OBJ drawableId;
{
    id drawable;

    drawable = (id)(_intVal(drawableId));
    if (drawable != lastDrawable) {
	if (lastDrawable) {
	    _objc_unlockFocus(lastDrawable);
	}
	_objc_lockFocus(drawable);
	lastDrawable = drawable;
    }
}

%}
! !

!NeXTWorkstation class methodsFor:'initialization'!

initialize
    self initializeDisplayConstants.
    self initializeConstants.
!

initializeDisplayConstants
    "initialize some common constants"
! !

!NeXTWorkstation class methodsFor:'queries'!

platformName
    ^ 'NeXTStep'
! !

!NeXTWorkstation methodsFor:'accessing & queries'!

blackpixel
    "return the colorId of black;
     for next, we use the color directly"

    ^ 16r000000
!

displayFileDescriptor
    "return the displays fileNumber - for select"

    ^ nil
!

hasDPS
    "return true, if display supports postscript output into a view"

    ^ true
!

hasShape
    "return true, if display supports arbitrary shaped windows.
     (actually, DPS does support this - but I currently dont know how)"

    ^ false
!

protocolVersion
    ^ self vendorRelease
!

serverVendor
    ^ 'NeXT'
!

translatePoint:aPoint from:windowId1 to:windowId2
    "given a point in window1, return the coordinate in window2
     - use to xlate points from a window to rootwindow"

     ^ self shouldNotImplement
!

vendorRelease
    ^ 2.1  "this is wrong - should get it from somewhere ..."
!

viewIdFromPoint:aPoint in:windowId
    "given a point in rootWindow, return the viewId of the subview of windowId
     hit by this coordinate.
     return nil if no view was hit.
     - use to find window to drop objects after a cross-view drag"

     ^ self shouldNotImplement
!

visualType:aSymbol
    ^ self shouldNotImplement
!

whitepixel
    "return the colorId of white;
     for next, we use the color directly"

    ^ 16rFFFFFF
! !

!NeXTWorkstation methodsFor:'bitmap/window creation'!

createBitmapFromArray:anArray width:w height:h
     ^ self shouldNotImplement
!

createBitmapFromFile:aString for:aForm
     ^ self shouldNotImplement
!

createBitmapWidth:w height:h
     ^ self shouldNotImplement
!

createFaxImageFromArray:data width:w height:h type:type k:k msbFirst:msbFirst
    "create a new faxImage in the workstation"

    ^ nil
!

createPixmapWidth:w height:h depth:d
     ^ self shouldNotImplement
!

createWindowFor:aView left:xpos top:ypos width:wwidth height:wheight

    |ext minWidth minHeight maxWidth maxHeight
     bWidth bColor viewBg viewBgId wsuperView wsuperViewId
     wlabel wcursor wcursorId wicon wiconId windowId
     wiconView wiconViewId
     drawableId|

    wsuperView := aView superView.
    wsuperView notNil ifTrue:[
	wsuperViewId := wsuperView id
    ].
    wlabel := aView label.
    wcursor := aView cursor.

    wsuperView isNil ifTrue:[
	ext := aView minExtent.
	ext notNil ifTrue:[
	    minWidth := ext x.
	    minHeight := ext y
	].
	ext := aView maxExtent.
	ext notNil ifTrue:[
	    maxWidth := ext x.
	    maxHeight := ext y
	].
    ].

%{
    id win;
    id view;
    int w, h, resizable;

    if ((minWidth != nil) && (maxWidth != nil)
     && (minWidth == maxWidth) && (minHeight == maxHeight)) {
	w = _intVal(minWidth);
	h = _intVal(maxHeight);
	resizable = 0;
    } else {
	w = _intVal(wwidth);
	h = _intVal(wheight);
	resizable = 1;
    }
    win = _NX_create_window(_intVal(xpos), _intVal(ypos), w, h, resizable);
    if (! win)
	return nil;

    /*
     * define its name
     */
    if (_isString(wlabel))
	_objc_setTitle(win, _stringVal(wlabel));
    else
	_objc_setTitle(win, "untitled");

    view = _objc_contentView(win);
    _objc_setFlipped_(view, 1);

    _objc_makeKeyAndOrderFront(win, 0);
    _objc_display(win);

    windowId = _MKSMALLINT(win);
    drawableId = _MKSMALLINT(view);
%}.
    self addKnownView:aView winId:windowId withId:drawableId.
    ^ drawableId
!

destroyFaxImage:aFaxImageId
     ^ self shouldNotImplement
!

destroyGC:aGCId
     ^ self shouldNotImplement
!

destroyPixmap:aDrawableId
     ^ self shouldNotImplement
!

destroyView:aView withId:aWindowId
     ^ self shouldNotImplement
!

gcFor:aDrawableId
     ^ self shouldNotImplement
!

rootWindowFor:aView
     ^ self shouldNotImplement
! !

!NeXTWorkstation methodsFor:'color stuff'!

colorCell
    "allocate a color - return index.
     Since NeXTs are either StaticGrey or StaticColor, return nil here."

    ^ nil
!

colorNamed:aString
    "allocate a color with color name - return index"

    ^ super colorNamed:aString
!

colorRed:redVal green:greenVal blue:blueVal
    "allocate a color with rgb values - return index"

    | r g b |

    "on the next, we use rgb value as index"
    r := (redVal * 16rFF / 100) asInteger.
    g := (greenVal * 16rFF / 100) asInteger.
    b := (blueVal * 16rFF / 100) asInteger.
    r := (r min:255) max:0.
    g := (g min:255) max:0.
    b := (b min:255) max:0.
    ^ (((r bitShift:8) bitOr:g) bitShift:8) bitOr:b
!

freeColor:colorIndex
    "colors are never freed"

    ^ self
!

getBlueFrom:index
    "get blue part of color in map at:index"

    ^ (index bitAnd:16rFF) * 100 / 16rFF
!

getGreenFrom:index
    "get green part of color in map at:index"

    ^ ((index bitShift:-8) bitAnd:16rFF) * 100 / 16rFF
!

getRedFrom:index
    "get red part of color in map at:index"

    ^ ((index bitShift:-16) bitAnd:16rFF) * 100 / 16rFF
!

listOfAvailableColors
    ^ super listOfAvailableColors
!

setColor:index red:redVal green:greenVal blue:blueVal
    "change color in map at:index.
     Since NeXTs are either StaticGrey or StaticColor, do nothing here."

    ^ self
! !

!NeXTWorkstation methodsFor:'cursor stuff'!

createCursorSourceFormId:sourceFormId maskFormId:maskFormId hotX:hx hotY:hy
    ^ self primitiveFailed
!

destroyCursor:aCursorId
    ^ self primitiveFailed
!

grabPointerIn:aWindowId
    ^ self primitiveFailed
!

pointerPosition
    ^ self primitiveFailed
!

ungrabPointer
    ^ self primitiveFailed
! !

!NeXTWorkstation methodsFor:'drawing'!

copyFromId:sourceId x:srcX y:srcY gc:srcGCId to:destId x:dstX y:dstY gc:dstGCId width:w height:h
    "do a bit-blt"

    ^ self primitiveFailed
!

copyPlaneFromId:sourceId x:srcX y:srcY gc:srcGCId to:destId x:dstX y:dstY gc:dstGCId width:w height:h
    "do a bit-blt"

    ^ self primitiveFailed
!

displayArcX:x y:y w:width h:height from:startAngle angle:angle
	       in:aDrawableId with:aGCId
    "draw an arc"

    ^ self primitiveFailed
!

displayLineFromX:x0 y:y0 toX:x1 y:y1 in:aDrawableId with:aGCId
    "draw a line"

%{
    float fx0, fy0, fx1, fy1;

    do {
	if (__isSmallInteger(x0))
	    fx0 = _intVal(x0);
	else if (_isFloat(x0))
	    fx0 = _floatVal(x0);
	else break;
	if (__isSmallInteger(y0))
	    fy0 = _intVal(y0);
	else if (_isFloat(y0))
	    fy0 = _floatVal(y0);
	else break;
	if (__isSmallInteger(x1))
	    fx1 = _intVal(x1);
	else if (_isFloat(x1))
	    fx1 = _floatVal(x1);
	else break;
	if (__isSmallInteger(y1))
	    fy1 = _intVal(y1);
	else if (_isFloat(y1))
	    fy1 = _floatVal(y1);
	else break;

	setDrawable(aDrawableId);
	PSsetlinewidth(0.0);
	PSnewpath();
	PSmoveto(fx0, fy0);
	PSlineto(fx1, fy1);
	PSstroke();
	if (_INST(buffered) == false)
	    NXPing();

	RETURN ( self );
    } while (1);
%}
.
    ^ self primitiveFailed
!

displayOpaqueString:aString from:index1 to:index2 x:x y:y in:aDrawableId with:aGCId
    "draw part of a string - draw both foreground and background"

    ^ self primitiveFailed
!

displayOpaqueString:aString x:x y:y in:aDrawableId with:aGCId
    "draw a string - draw both foreground and background"

    ^ self primitiveFailed
!

displayPointX:x y:y in:aDrawableId with:aGCId
    "draw a point"

    ^ self primitiveFailed
!

displayString:aString from:index1 to:index2 x:x y:y in:aDrawableId with:aGCId
    "draw part of a string - draw foreground only"

    ^ self primitiveFailed
!

displayString:aString x:x y:y in:aDrawableId with:aGCId
    "draw a string - draw foreground only"

%{
    float fx, fy;

    do {
	if (__isSmallInteger(x))
	    fx = (float)_intVal(x);
	else if (_isFloat(x))
	    fx = _floatVal(x);
	else break;
	if (__isSmallInteger(y))
	    fy = (float)_intVal(y);
	else if (_isFloat(y))
	    fy = _floatVal(y);
	else break;
	setDrawable(aDrawableId);
	PSmoveto(fx, fy);
	PSshow((char *)_stringVal(aString));
	if (_INST(buffered) == false)
	    NXPing();
	RETURN ( self );
    } while (1);
%}
.
    self primitiveFailed
!

drawBits:imageBits depth:imageDepth width:imageWidth height:imageHeight
		       x:srcx y:srcy
		    into:aDrawableId x:dstx y:dsty width:w height:h with:aGCId
    "draw a bitimage which has depth id, width iw and height ih into
     the drawable. draw a region of w/h pixels from srcx/srcy to dstx/dsty.
     It has to be checked elsewhere, that server can do it with the given
     depth; also it is assumed, that the colormap is setup correctly"

    ^ self primitiveFailed
!

drawPolygon:aPolygon in:aDrawableId with:aGCId
    "draw a polygon"

    ^ self primitiveFailed
!

drawRectangleX:x y:y width:width height:height in:aDrawableId with:aGCId
    "draw a rectangle"

    ^ self primitiveFailed
!

fillArcX:x y:y w:width h:height from:startAngle angle:angle
	       in:aDrawableId with:aGCId
    "fill an arc"

    ^ self primitiveFailed
!

fillPolygon:aPolygon in:aDrawableId with:aGCId
    "fill a polygon"

    ^ self primitiveFailed
!

fillRectangleX:x y:y width:w height:h in:aDrawableId with:aGCId
    "fill a rectangle"

%{
    float fx, fy, fw, fh;

    do {
	if (__isSmallInteger(x))
	    fx = (float)_intVal(x);
	else if (_isFloat(x))
	    fx = _floatVal(x);
	else break;
	if (__isSmallInteger(y))
	    fy = (float)_intVal(y);
	else if (_isFloat(y))
	    fy = _floatVal(y);
	else break;

	if (__isSmallInteger(w))
	    fw = (float)_intVal(w);
	else if (_isFloat(w))
	    fw = _floatVal(w);
	else break;
	if (__isSmallInteger(h))
	    fh = (float)_intVal(h);
	else if (_isFloat(h))
	    fh = _floatVal(h);
	else break;

	setDrawable(aDrawableId);
	PSnewpath();
	PSmoveto(fx, fy);
	PSlineto(fx + fw, fy);
	PSlineto(fx + fx, fy + fh);
	PSlineto(fx, fy + fh);
	PSlineto(fx, fy);
	PSclosepath();
	PSfill();
	if (_INST(buffered) == false)
	    NXPing();
	RETURN ( self );
    } while (1);
%}
! !

!NeXTWorkstation methodsFor:'events'!

eventMaskFor:anEventSymbol
    ^ self primitiveFailed
!

eventPending
    "return true, if any event is pending"

    ^ false
!

eventPending:anEventSymbol for:aWindowId
    "return true, if a specific event is pending"

    ^ self primitiveFailed
!

eventPendingWithoutSync
    "return true, if any event is pending"

    ^ false
!

eventsPending:anEventMask for:aWindowId
    "return true, if any of the masked events is pending"

    ^ self primitiveFailed
!

exposeEventsFor:aViewId do:aBlock
!

setEventMask:aMask in:aWindowId
    ^ self primitiveFailed
! !

!NeXTWorkstation methodsFor:'font stuff'!

ascentOf:aFontId
    ^ self primitiveFailed
!

createFontFor:aFontName
    ^ self primitiveFailed
!

descentOf:aFontId
    self badFont
!

listOfAvailableFonts
    "return a list with all available font names on this display"
%{
	char **names;
	char **cp;
	int count, i;
	static struct inlineCache dummy1 = _DUMMYILC1;
	OBJ arr;

	names = (char **) _objc_availableFonts(_FontManager_new());
	/* count them */
	for (cp = names; *cp; cp++) ;;
	count = cp - names;
	arr = _SEND1(@global(Array), @symbol(new:), nil, &dummy1, _MKSMALLINT(count));
	for (i=0; i<count;i++)
	    _ArrayInstPtr(arr)->a_element[i] = __MKSTRING(names[i]);
	free(names);
	RETURN (arr);
%}
!

maxWidthOfFont:aFontId
    self badFont
!

minWidthOfFont:aFontId
    self badFont
!

releaseFont:aFontId
    ^ self primitiveFailed
!

widthOf:aString from:index1 to:index2 inFont:aFontId
    ^ self primitiveFailed
!

widthOf:aString inFont:aFontId
    ^ self primitiveFailed
! !

!NeXTWorkstation methodsFor:'graphic context stuff'!

noClipIn:aDrawableId gc:aGCId
    "disable clipping rectangle"

    ^ self primitiveFailed
!

setBackground:bgColorIndex in:aGCId
    "set background color to be drawn with"

    ^ self primitiveFailed
!

setBitmapMask:aBitmapId in:aGCId
    "set or clear the drawing mask - a bitmap mask using current fg/bg"

    ^ self primitiveFailed
!

setClipByChildren:aBool in:aGCId
    "enable/disable drawing into child views"

    ^ self primitiveFailed
!

setClipX:clipX y:clipY width:clipWidth height:clipHeight in:drawableId gc:aGCId
    "clip to a rectangle"

    ^ self primitiveFailed
!

setFont:aFontId in:aGCId
    "set font to be drawn in"

    ^ self primitiveFailed
!

setForeground:fgColorIndex background:bgColorIndex in:aGCId
    "set foreground and background colors to be drawn with"

    ^ self primitiveFailed
!

setForeground:fgColor background:bgColor mask:aBitmapId in:aGCId
    "set foreground and background colors to be drawn with using mask or
     solid (if aBitmapId is nil)"

    ^ self primitiveFailed
!

setForeground:fgColor background:bgColor mask:aBitmapId lineWidth:lw in:aGCId
    "set foreground and background colors to be drawn with using mask or
     solid (if aBitmapId is nil); also set lineWidth"

    ^ self primitiveFailed
!

setForeground:fgColorIndex in:aGCId
    "set foreground color to be drawn with"

    ^ self primitiveFailed
!

setFunction:aFunctionSymbol in:aGCId
    "set alu function to be drawn with"

    "{ Symbol: and  } "
    "{ Symbol: or   } "
    "{ Symbol: xor  } "
    "{ Symbol: copy } "
    "{ Symbol: copyInverted } "
    "{ Symbol: andInverted } "
    "{ Symbol: andReverse } "
    "{ Symbol: orInverted } "
    "{ Symbol: orReverse } "

    ^ self primitiveFailed
!

setGraphicsExposures:aBoolean in:aGCId
    "set or clear the graphics exposures flag"

    ^ self primitiveFailed
!

setLineWidth:aNumber in:aGCId
    "set linewidth to be drawn with"

    ^ self primitiveFailed
!

setMaskOriginX:orgX y:orgY in:aGCid
    "set the mask origin"

    ^ self primitiveFailed
!

setPixmapMask:aPixmapId in:aGCId
    "set or clear the drawing mask - a pixmap mask providing full color"

    ^ self primitiveFailed
! !

!NeXTWorkstation methodsFor:'initialize / release'!

close
%{
    _NX_close();
%}
!

initialize
    "{ Symbol: color      }"
    "{ Symbol: monochrome }"
%{
    int depth, width, height;
    char *visual;

    /* do NXApp stuff, get screen infos */
    _NX_init(&visual, &depth, &width, &height);

    _INST(visualType) = _MKSYMBOL(visual, (OBJ *)0);
    _INST(depth) = _MKSMALLINT(depth);
    _INST(width) = _MKSMALLINT(width);
    _INST(height) = _MKSMALLINT(height);

    _INST(widthMM) = _MKSMALLINT(300);
    _INST(heightMM) = _MKSMALLINT(222);

    if (strcmp(visual, "StaticGray") == 0) {
	_INST(hasColors) = false;
	_INST(hasGreyscales) = true;
	_INST(bitsPerRGB) = _MKSMALLINT(2);
	if (depth == 2)
	    _INST(ncells) = _MKSMALLINT(4);
	_INST(monitorType) = _monochrome;
    } else if (strcmp(visual, "TrueColor") == 0) {
	_INST(hasColors) = true;
	_INST(hasGreyscales) = true;
	/*
	 * does this exist ?"
	 *
	if (depth == 8) {
	    _INST(ncells) = _MKSMALLINT(256);
	}
	 *
	 */
	/* should work for colorStation */
	if (depth == 12) {
	    _INST(ncells) = _MKSMALLINT(4096);
	    _INST(bitsPerRGB) = _MKSMALLINT(4);
	}
	/* should work for nextDimension */
	if (depth == 24) {
	    _INST(ncells) = _MKSMALLINT(4096 * 4096);
	    _INST(bitsPerRGB) = _MKSMALLINT(8);
	}
	_INST(monitorType) = _color;
    }
%}
.
    dispatching := false.
    shiftDown := false.
    ctrlDown := false.
    metaDown := false.
    altDown := false.
    motionEventCompression := true.
    buffered := true.
    self initializeKeyboardMap
! !

!NeXTWorkstation methodsFor:'misc'!

buffered
    "buffer drawing - do not send it immediately to the display"

    buffered := true
!

lastError
    "return the last X-error string - when buffering is on, this may be
     an error for a long-ago operation"

    ^ nil
!

synchronizeOutput
    "send all buffered drawing to the display"
%{
    NXPing();
%}
!

unBuffered
    "make all drawing be sent immediately to the display"

    buffered := false
! !

!NeXTWorkstation methodsFor:'misc stuff'!

setInputFocusTo:aWindowId
    ^ self primitiveFailed
! !

!NeXTWorkstation methodsFor:'private'!

addKnownView:aView winId:aNumber withId:aDrawableNumber
    "add the View aView with Id:aNumber to the list of known views/id's"

    knownViews isNil ifTrue:[
	knownViews := OrderedCollection new:100.
	knownIds := OrderedCollection new:100.
	knownDrawableIds := OrderedCollection new:100
    ].
    knownViews add:aView.
    knownIds add:aNumber.
    knownDrawableIds add:aDrawableNumber
! !

!NeXTWorkstation methodsFor:'retrieving pixels'!

getPixelX:x y:y from:aDrawableId
    "return the pixel value at x/y"

    ^ self primitiveFailed
! !

!NeXTWorkstation methodsFor:'window stuff'!

clearRectangleX:x y:y width:width height:height in:aWindowId
    ^ self primitiveFailed
!

clearWindow:aWindowId
    ^ self primitiveFailed
!

mapWindow:aWindowId
    ^ self primitiveFailed
!

moveResizeWindow:aWindowId x:x y:y width:w height:h
    ^ self primitiveFailed
!

moveWindow:aWindowId x:x y:y
    ^ self primitiveFailed
!

raiseWindow:aWindowId
    ^ self primitiveFailed
!

resizeWindow:aWindowId width:w height:h
    ^ self primitiveFailed
!

setBackingStore:how in:aWindowId
    "turn on/off backing-store for a window"

    ^ self
!

setCursor:aCursorId in:aWindowId
    ^ self primitiveFailed
!

setSaveUnder:yesOrNo in:aWindowId
    "turn on/off save-under for a window"

    ^ self
!

setWindowBackground:aColorId in:aWindowId
%{
#ifdef NOTDEF
    int id, ir, ig, ib;
    float r, g, b;
    NXColor clr;

    if (__isSmallInteger(aColorId)) {
	id = _intVal(aColorId);
	ir = (id >> 16) & 0xFF;
	ig = (id >> 8) & 0xFF;
	ib = id & 0xFF;
	/* scale from 0 .. 255 to 0.0 .. 1.0 */
	r = (float)ir / 255.0;
	g = (float)ig / 255.0;
	b = (float)ib / 255.0;
	clr = NXConvertRGBToColor(r, g, b);
    }
#endif
%}
.
    ^ self primitiveFailed
!

setWindowBackgroundPixmap:aPixmapId in:aWindowId
    ^ self primitiveFailed
!

setWindowBorderColor:aColorId in:aWindowId
    ^ self primitiveFailed
!

setWindowBorderPixmap:aPixmapId in:aWindowId
    ^ self primitiveFailed
!

setWindowBorderShape:aPixmapId in:aWindowId
    ^ self
!

setWindowBorderWidth:aNumber in:aWindowId
    ^ self primitiveFailed
!

setWindowIcon:aForm in:aWindowId
    ^ self primitiveFailed
!

setWindowIcon:aForm mask:aMaskForm in:aWindowId
    ^ self primitiveFailed
!

setWindowIconWindow:aView in:aWindowId
    ^ self primitiveFailed
!

setWindowName:aString in:aWindowId
    ^ self primitiveFailed
!

setWindowShape:aPixmapId in:aWindowId
    ^ self
!

unmapWindow:aWindowId
    ^ self primitiveFailed
! !


NeXTWorkstation initialize!