123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853 |
- (* ETH Oberon, Copyright 2000 ETH Zürich Institut für Computersysteme, ETH Zentrum, CH-8092 Zürich.
- Refer to the general ETH Oberon System license contract available at: http://www.oberon.ethz.ch/ *)
- MODULE XDisplay; (** AUTHOR "gf"; PURPOSE "display driver plugin for X Windows *)
- IMPORT S := SYSTEM, Trace, Unix, Machine, Files, UnixFiles, X11, Api := X11Api, Displays, Strings;
- CONST
- BG = 0; FG = 15; (* Background, foreground colors.*)
- CONST
- (* formats for Transfer. value DIV 8 = bytes per pixel. *)
- unknown = 0;
- index8 = 8; color555 = 16; color565 = 17; color664 = 18;
- color888 = 24; color8888* = 32;
- (* Drawing operation modes. *)
- replace = 0; (* destcolor := sourcecolor. *)
- paint = 1; (* destcolor := destcolor OR sourcecolor. *)
- invert = 2; (* destcolor := destcolor XOR sourcecolor. *)
- VAR
- winName, iconName: ARRAY 128 OF CHAR;
- TYPE
-
- RGB = RECORD
- r, g, b: INTEGER
- END;
- Clip* = OBJECT
- VAR
- d: Display; lx, ly, lw, lh: LONGINT;
- PROCEDURE & Init( disp: Display );
- BEGIN
- d := disp; lx := 0; ly := 0; lw := 0; lh := 0;
- Reset
- END Init;
- PROCEDURE Set*( x, y, w, h: LONGINT );
- VAR rect: X11.Rectangle;
- BEGIN
- IF w < 0 THEN w := 0 END;
- IF h < 0 THEN h := 0 END;
- IF (x # lx) OR (y # ly) OR (w # lw) OR (h # lh) THEN
- lx := x; ly := y; lw := w; lh := h;
- IF y < d.height THEN d.currwin := d.primary ELSE d.currwin := d.secondary; DEC( y, d.height ) END;
- rect.x := SHORT( x ); rect.y := SHORT( y );
- rect.w := SHORT( w ); rect.h := SHORT( h );
- Machine.Acquire( Machine.X11 );
- IF (rect.x <= 0) & (rect.y <= 0) & (rect.w >= d.width) & (rect.h >= d.height) THEN
- X11.SetClipMask( d.xdisp, d.gc, X11.None ) (* no clipping *)
- ELSE
- X11.SetClipRectangles( d.xdisp, d.gc, 0, 0, ADDRESSOF( rect ), 1, X11.YXBanded )
- END;
- Machine.Release( Machine.X11 )
- END;
- END Set;
- PROCEDURE Get*( VAR x, y, w, h: LONGINT );
- BEGIN
- x := lx; y := ly; w := lw; h := lh
- END Get;
- PROCEDURE InClip*( x, y, w, h: LONGINT ): BOOLEAN;
- BEGIN
- RETURN (x >= lx) & (x + w <= lx + lw) & (y >= ly) & (y + h <= ly + lh)
- END InClip;
- PROCEDURE Reset*;
- BEGIN
- Set( 0, 0, d.width, d.height );
- END Reset;
- (** Intersect with current clip rectangle resulting in a new clip rectangle. *)
- PROCEDURE Adjust*( x, y, w, h: LONGINT ); (* intersection *)
- VAR x0, y0, x1, y1: LONGINT;
- BEGIN
- IF x > lx THEN x0 := x ELSE x0 := lx END;
- IF y > ly THEN y0 := y ELSE y0 := ly END;
- IF x + w < lx + lw THEN x1 := x + w ELSE x1 := lx + lw END;
- IF y + h < ly + lh THEN y1 := y + h ELSE y1 := ly + lh END;
- Set( x0, y0, x1 - x0, y1 - y0 );
- END Adjust;
- END Clip;
- Display* = OBJECT (Displays.Display)
- VAR
- xdisp- : X11.DisplayPtr;
- primary- : X11.Window;
- secondary- : X11.Window;
- currwin : X11.Window;
- wmDelete- : X11.Atom;
- screen : LONGINT;
- visual{UNTRACED} : X11.VisualPtr;
- depth : LONGINT;
- bigEndian : BOOLEAN;
- gc : X11.GC;
- clip : Clip;
-
- cmap : X11.Colormap;
- planesMask : LONGINT;
- foreground,
- background : LONGWORD;
- rgb, defPal : ARRAY 256 OF RGB; (* 8-bit pseudo color *)
- pixel : ARRAY 256 OF LONGINT; (* pixel values for Oberon colors *)
- xformat : LONGINT;
- currcol, currmode : LONGINT;
- xfunc : ARRAY 3 OF LONGINT;
-
-
- PROCEDURE SetMode( col: LONGINT );
- VAR mode: LONGINT;
- BEGIN
- mode := replace;
- IF (col # -1) & (30 IN S.VAL( SET, col )) THEN mode := invert; EXCL( S.VAL( SET, col ), 30 ) END;
- IF mode # currmode THEN X11.SetFunction( xdisp, gc, xfunc[mode] ); currmode := mode END;
- IF col # currcol THEN X11.SetForeground( xdisp, gc, ColorToPixel( col ) ); currcol := col END;
- END SetMode;
- PROCEDURE Dot*( col, x, y: LONGINT );
- BEGIN
- IF currwin = secondary THEN DEC( y, height ) END;
- Machine.Acquire( Machine.X11 );
- SetMode( col );
- X11.DrawPoint( xdisp, currwin, gc, x, y );
- Machine.Release( Machine.X11 )
- END Dot;
- PROCEDURE Fill*( col, x, y, w, h: LONGINT );
- BEGIN
- IF (h > 0) & (w > 0) THEN
- IF currwin = secondary THEN DEC( y, height ) END;
- Machine.Acquire( Machine.X11 );
- SetMode( col );
- X11.FillRectangle( xdisp, currwin, gc, x, y, w, h );
- Machine.Release( Machine.X11 )
- END
- END Fill;
- (** Transfer a block of pixels in "raw" display format to (op = set) or from (op = get) the display.
- Pixels in the rectangular area are transferred from left to right and top to bottom. The pixels
- are transferred to or from "buf", starting at "ofs". The line byte increment is "stride", which may
- be positive, negative or zero. *)
- PROCEDURE Transfer*( VAR buf: ARRAY OF CHAR; ofs, stride, x, y, w, h, op: LONGINT );
- CONST Get = 0; Set = 1;
- VAR image: X11.Image;
- imp: X11.ImagePtr;
- bp, ip: ADDRESS;
- line, ll: LONGINT;
- BEGIN
- ll := w*(xformat DIV 8);
- IF (ofs + (h - 1)*stride + ll > LEN( buf )) OR (ofs + (h - 1)*stride < 0) THEN HALT( 99 ) END;
-
- IF LEN( imgBuffer ) < 4*w*h THEN
- NEW( imgBuffer, 4*w*h ); (* create buffer outside lock to avoid deadlock *)
- END;
-
- bp := ADDRESSOF( buf[ofs] );
- IF op = Set THEN
- Machine.Acquire( Machine.X11 );
- image := X11.CreateImage( xdisp, visual, depth, X11.ZPixmap, 0, 0, w, h, 32, 0 );
- imp := S.VAL( X11.ImagePtr, image );
- imp.data := ADDRESSOF( imgBuffer[0] ); ip := imp.data;
- IF imp.byteOrder = 0 THEN
- FOR line := 0 TO h - 1 DO
- PutLine( xformat, w, ip, bp );
- INC( bp, stride ); INC( ip, imp.bytesPerLine )
- END;
- ELSE
- FOR line := 0 TO h - 1 DO
- PutLineBE( xformat, w, ip, bp );
- INC( bp, stride ); INC( ip, imp.bytesPerLine )
- END;
- END;
- IF currmode # replace THEN
- X11.SetFunction( xdisp, gc, xfunc[replace] ); currmode := replace
- END;
- X11.PutImage( xdisp, primary, gc, image, 0, 0, x, y, w, h );
- X11.Free( image ); imp := NIL;
- Machine.Release( Machine.X11 )
- ELSIF op = Get THEN
- Machine.Acquire( Machine.X11 );
- image := X11.GetImage( xdisp, primary, x, y, w, h, planesMask, X11.ZPixmap );
- imp := S.VAL( X11.ImagePtr, image ); ip := imp.data;
- IF imp.byteOrder = 0 THEN
- FOR line := 0 TO h - 1 DO
- GetLine( xformat, w, ip, bp );
- INC( bp, stride ); INC( ip, imp.bytesPerLine )
- END
- ELSE
- FOR line := 0 TO h - 1 DO
- GetLineBE( xformat, w, ip, bp );
- INC( bp, stride ); INC( ip, imp.bytesPerLine )
- END
- END;
- X11.Free( imp.data ); X11.Free( image ); imp := NIL;
- Machine.Release( Machine.X11 )
- END;
- END Transfer;
- (** Transfer a block of pixels from a 1-bit mask to the display. Pixels in the rectangular area are
- transferred from left to right and top to bottom. The pixels are transferred from "buf", starting
- at bit offset "bitofs". The line byte increment is "stride", which may be positive, negative or zero.
- "fg" and "bg" specify the colors for value 1 and 0 pixels respectively. *)
- PROCEDURE Mask*( VAR buf: ARRAY OF CHAR; bitofs, stride, fg, bg, x, y, w, h: LONGINT );
- VAR p: ADDRESS; i: LONGINT; s: SET;
- image: X11.Image;
- fgpixel, bgpixel, xret: LONGINT;
- ix, iy, ih: LONGINT;
- imp: X11.ImagePtr;
- BEGIN
- IF (w > 0) & (h > 0) THEN
- IF fg >= 0 THEN fgpixel := pixel[fg MOD 256] ELSE fgpixel := ColorToPixel( fg ) END;
- IF bg >= 0 THEN bgpixel := pixel[bg MOD 256] ELSE bgpixel := ColorToPixel( bg ) END;
- IF LEN( imgBuffer ) < 4*w*h THEN
- NEW( imgBuffer, 4*w*h ); (* create buffer outside lock to avoid deadlock *)
- END;
- Machine.Acquire( Machine.X11 );
- image := X11.CreateImage( xdisp, visual, depth, X11.ZPixmap, 0, 0, w, h, 32, 0 );
- imp := S.VAL( X11.ImagePtr, image );
- imp.data := ADDRESSOF( imgBuffer[0] );
- i := LONGINT(ADDRESSOF( buf[0] ) MOD 4); INC( bitofs, i*8 );
- p := ADDRESSOF( buf[0] ) - i + bitofs DIV 32*4; (* p always aligned to 32-bit boundary *)
- bitofs := bitofs MOD 32; stride := stride*8;
- ix := 0; iy := 0; ih := h;
- LOOP
- S.GET( p, s ); i := bitofs;
- LOOP
- IF (i MOD 32) IN s THEN xret := X11.PutPixel( image, ix, iy, fgpixel );
- ELSE xret := X11.PutPixel( image, ix, iy, bgpixel );
- END;
- INC( i ); INC( ix );
- IF i - bitofs = w THEN EXIT END;
- IF i MOD 32 = 0 THEN S.GET( p + i DIV 8, s ) END
- END;
- DEC( ih );
- IF ih = 0 THEN EXIT END;
- INC( iy ); ix := 0; INC( bitofs, stride );
- IF (bitofs >= 32) OR (bitofs < 0) THEN (* moved outside s *)
- INC( p, bitofs DIV 32*4 ); bitofs := bitofs MOD 32
- END
- END; (* loop *)
- IF currmode # replace THEN X11.SetFunction( xdisp, gc, xfunc[replace] ) END;
- X11.PutImage( xdisp, primary, gc, image, 0, 0, x, y, w, h );
- IF currmode # replace THEN X11.SetFunction( xdisp, gc, xfunc[currmode] ) END;
- X11.Free( image );
- Machine.Release( Machine.X11 );
- END
- END Mask;
- (** Copy source block sx, sy, w, h to destination dx, dy. Overlap is allowed. *)
- PROCEDURE Copy*( sx, sy, w, h, dx, dy: LONGINT );
- VAR src: X11.DisplayPtr;
- BEGIN
- IF (w > 0) & (h > 0) THEN
- IF sy < height THEN src := primary ELSE src := secondary; DEC( sy, height ) END;
- IF currwin = secondary THEN DEC( sy, height ) END;
- Machine.Acquire( Machine.X11 );
- SetMode( currcol );
- X11.CopyArea( xdisp, src, currwin, gc, sx, sy, w, h, dx, dy );
- Machine.Release( Machine.X11 )
- END;
- END Copy;
- (** Update the visible display (if caching is used). *)
- PROCEDURE Update*;
- BEGIN
- Machine.Acquire( Machine.X11 );
- X11.Sync( xdisp, X11.False );
- Machine.Release( Machine.X11 )
- END Update;
- (** Map a color value to an 8-bit CLUT index. Only used if xformat = index8. *)
- PROCEDURE ColorToIndex*( col: LONGINT ): LONGINT;
- BEGIN
- RETURN ColorToIndex0( SELF, col )
- END ColorToIndex;
- (** Map an 8-bit CLUT index to a color value. Only used if xformat = index8. *)
- PROCEDURE IndexToColor*( n: LONGINT ): LONGINT;
- VAR r, g, b: LONGINT;
- BEGIN
- IF n >= 0 THEN
- IF n > 255 THEN n := BG END;
- r := rgb[n].r; g := rgb[n].g; b := rgb[n].b;
- RETURN MIN( LONGINT ) + (r*100H + g)*100H + b
- ELSE RETURN n
- END;
- END IndexToColor;
- PROCEDURE SetColor*( col, red, green, blue: INTEGER ); (* 0 <= col, red, green, blue < 256 *)
- VAR xcol: X11.Color; res: LONGINT;
- BEGIN
- IF (col < 0) OR (col > 255) THEN RETURN END;
- rgb[col].r := red; rgb[col].g := green; rgb[col].b := blue;
- xcol.red := 256*red; xcol.green := 256*green; xcol.blue := 256*blue;
- Machine.Acquire( Machine.X11 );
- IF depth > 8 THEN
- res := X11.AllocColor( xdisp, cmap, ADDRESSOF( xcol ) );
- IF res # 0 THEN pixel[col] := LONGINT (xcol.pixel) END
- ELSE
- xcol.flags := CHR( X11.DoAll ); xcol.pixel := pixel[col];
- X11.StoreColor( xdisp, cmap, ADDRESSOF( xcol ) )
- END;
- Machine.Release( Machine.X11 )
- END SetColor;
- PROCEDURE GetColor*( col: INTEGER; VAR red, green, blue: INTEGER );
- BEGIN
- IF (0 <= col) & (col <= 255) THEN
- red := rgb[col].r; green := rgb[col].g; blue := rgb[col].b
- ELSE
- red := rgb[BG].r; green := rgb[BG].g; blue := rgb[BG].b
- END
- END GetColor;
- PROCEDURE ColorToPixel*( col: LONGINT ): LONGINT;
- VAR r, g, b, i, ii, x, y, z, m, min: LONGINT; rc: RGB;
- BEGIN
- r := LSH( col, -16 ) MOD 256; g := LSH( col, -8 ) MOD 256; b := col MOD 256;
- CASE xformat OF
- color8888, color888:
- IF bigEndian THEN RETURN ASH( b, 16 ) + ASH( g, 8 ) + r
- ELSE RETURN ASH( r, 16 ) + ASH( g, 8 ) + b
- END
- | color555:
- r := 32*r DIV 256; g := 32*g DIV 256; b := 32*b DIV 256;
- IF bigEndian THEN RETURN ASH( b, 10 ) + ASH( g, 5 ) + r
- ELSE RETURN ASH( r, 10 ) + ASH( g, 5 ) + b
- END
- | color565:
- r := 32*r DIV 256; g := 64*g DIV 256; b := 32*b DIV 256;
- IF bigEndian THEN RETURN ASH( b, 11 ) + ASH( g, 5 ) + r
- ELSE RETURN ASH( r, 11 ) + ASH( g, 5 ) + b
- END
- | color664:
- r := 64*r DIV 256; g := 64*g DIV 256; b := 16*b DIV 256;
- IF bigEndian THEN RETURN ASH( b, 12 ) + ASH( g, 6 ) + r
- ELSE RETURN ASH( r, 10 ) + ASH( g, 4 ) + b
- END
- ELSE (* index8 *)
- i := 0; ii := 0; min := MAX( LONGINT );
- WHILE (i < 256) & (min > 0) DO
- rc := rgb[i];
- x := ABS( r - rc.r ); y := ABS( g - rc.g ); z := ABS( b - rc.b ); m := x;
- IF y > m THEN m := y END;
- IF z > m THEN m := z END;
- m := m*m + (x*x + y*y + z*z);
- IF m < min THEN min := m; ii := i END;
- INC( i )
- END;
- RETURN pixel[ii]
- END
- END ColorToPixel;
- PROCEDURE & Initialize( disp: X11.DisplayPtr; absWidth, absHeight, relWidth, relHeight: LONGINT );
- VAR
- event: Api.XEvent; root: X11.Window;
- gRoot, gX, gY, gW, gH, gBW, gD, res: LONGINT; screenw, screenh : LONGINT;
- BEGIN
-
- xdisp := disp;
- screen := X11.DefaultScreen( xdisp );
- screenw := X11.DisplayWidth( xdisp, screen );
- screenh := X11.DisplayHeight( xdisp, screen );
- depth := X11.DefaultDepth( xdisp, screen );
- cmap := X11.DefaultColormap( xdisp, screen );
- foreground := X11.BlackPixel( xdisp, screen );
- background := X11.WhitePixel( xdisp, screen );
- Machine.Acquire( Machine.X11 );
- root := X11.DefaultRootWindow( xdisp );
- primary := X11.CreateSimpleWindow( xdisp, root, 0, 0,
- screenw - 16, screenh - 32, 0,
- foreground, background );
- X11.StoreName( xdisp, primary, ADDRESSOF( winName ) );
- X11.SetIconName( xdisp, primary, ADDRESSOF( iconName ) );
- X11.SetCommand( xdisp, primary, Unix.argv, Unix.argc );
- X11.SelectInput( xdisp, primary, X11.ExposureMask );
-
-
- (* set wm_delete_events if in windowed mode *)
- wmDelete := Api.InternAtom(xdisp, "WM_DELETE_WINDOW", Api.True);
- res := Api.SetWMProtocols(xdisp, primary, ADDRESSOF(wmDelete), 1);
-
- X11.MapRaised( xdisp, primary );
- REPEAT Api.NextEvent( xdisp, event )
- UNTIL (event.typ = Api.Expose) & (event.window = primary);
- (* adjust to physical window size *)
- X11.GetGeometry( xdisp, primary, gRoot, gX, gY, gW, gH, gBW, gD );
- IF relWidth # -1 THEN
- gW := relWidth * gW DIV 100;
- ELSE
- gW := absWidth;
- END;
- IF relHeight # -1 THEN
- gH := relHeight * gH DIV 100;
- ELSE
- gH := absHeight;
- END;
- IF gW MOD 8 # 0 THEN DEC( gW, gW MOD 8 ) END;
- X11.ResizeWindow( xdisp, primary, gW, gH );
- width := gW; height := gH;
- offscreen := height;
- (* pixmap may not be larger than screen: *)
- IF gW > screenw THEN gW := screenw END;
- IF gH > screenh THEN gH := screenh END;
- secondary := X11.CreatePixmap( xdisp, primary, gW, gH, depth );
- Machine.Release( Machine.X11 );
- CreateColors( SELF ); InitPalette( SELF ); SuppressX11Cursors( SELF );
- InitFormat( SELF ); CreateGC( SELF ); InitFunctions( SELF );
- NEW( clip, SELF )
- END Initialize;
- (** Finalize the display. Further calls to display methods are not allowed, and may cause exceptions. *)
- PROCEDURE Finalize*;
- (*
- BEGIN (* should really be exclusive with Transfer, but we assume the caller keeps to the rules above *)
- fbadr := 0; fbsize := 0
- *)
- END Finalize;
- END Display;
- VAR
- dispname: ARRAY 128 OF CHAR;
-
- imgBuffer: POINTER TO ARRAY OF CHAR;
- PROCEDURE ColorToIndex0( disp: Display; col: LONGINT ): INTEGER;
- VAR idx, i: INTEGER; r, g, b, min, x, y, z, d: LONGINT; rc: RGB;
- BEGIN
- r := ASH( col, -16 ) MOD 100H; g := ASH( col, -8 ) MOD 100H; b := col MOD 100H;
- i := 0; idx := 0; min := MAX( LONGINT );
- WHILE (i < 256) & (min > 0) DO
- rc := disp.defPal[i]; x := ABS( r - rc.r ); y := ABS( g - rc.g ); z := ABS( b - rc.b ); d := x;
- IF y > d THEN d := y END;
- IF z > d THEN d := z END;
- d := d*d + (x*x + y*y + z*z);
- IF d < min THEN min := d; idx := i END;
- INC( i )
- END;
- RETURN idx
- END ColorToIndex0;
- PROCEDURE PutLine( xformat, width: LONGINT; ip, bp: ADDRESS );
- VAR i: LONGINT; byte: CHAR;
- BEGIN
- CASE xformat OF
- | index8:
- S.MOVE(bp, ip, width);
- | color565, color555, color664:
- S.MOVE(bp, ip, 2*width);
- | color888: (* x-format (destination) is 888, A ignored (?) , Aos Format (source) is 8888 *)
- S.MOVE(bp, ip, 4*width);
- (*
- FOR i := 1 TO width DO
- S.MOVE(bp,ip,3); INC(bp,3); INC(ip,3);
- (*
- S.GET( bp, byte ); S.PUT( ip, byte ); INC( bp ); INC( ip ); (* B *)
- S.GET( bp, byte ); S.PUT( ip, byte ); INC( bp ); INC( ip ); (* G *)
- S.GET( bp, byte ); S.PUT( ip, byte ); INC( bp ); INC( ip ); (* R *)
- *)
- byte := 0X; S.PUT( ip, byte ); INC( ip )
- END;
- *)
- ELSE (* color8888 *)
- S.MOVE(bp, ip, 4*width);
- END
- END PutLine;
- PROCEDURE GetLine( xformat, width: LONGINT; ip, bp: ADDRESS );
- VAR i: LONGINT; byte: CHAR;
- BEGIN
- CASE xformat OF
- | index8:
- S.MOVE(ip, bp, width);
- | color565, color555, color664:
- S.MOVE(ip, bp, 2*width);
- | color888:
- S.MOVE(ip, bp, 4*width);
- (*
- FOR i := 1 TO width DO
- S.GET( ip, byte ); S.PUT( bp, byte ); INC( ip ); INC( bp ); (* B *)
- S.GET( ip, byte ); S.PUT( bp, byte ); INC( ip ); INC( bp ); (* G *)
- S.GET( ip, byte ); S.PUT( bp, byte ); INC( ip ); INC( bp ); (* R *)
- INC( ip )
- END
- *)
- ELSE (* color8888 *)
- S.MOVE(ip, bp, 4*width);
- END;
- END GetLine;
- PROCEDURE PutLineBE( xformat, width: LONGINT; ip, bp: ADDRESS );
- VAR i: LONGINT; byte: CHAR;
- BEGIN
- CASE xformat OF
- index8:
- FOR i := 1 TO width DO
- S.GET( bp, byte ); S.PUT( ip, byte ); INC( bp ); INC( ip )
- END
- | color565, color555, color664:
- FOR i := 1 TO width DO
- S.GET( bp + 1, byte ); S.PUT( ip, byte ); INC( ip );
- S.GET( bp + 0, byte ); S.PUT( ip, byte ); INC( ip );
- INC( bp, 2 )
- END
- | color888:
- FOR i := 1 TO width DO
- S.PUT8( ip, 0X ); INC( ip );
- S.GET( bp + 2, byte ); S.PUT( ip, byte ); INC( ip ); (* B *)
- S.GET( bp + 1, byte ); S.PUT( ip, byte ); INC( ip ); (* G *)
- S.GET( bp + 0, byte ); S.PUT( ip, byte ); INC( ip ); (* R *)
- INC( bp, 4 )
- END
- ELSE (* color8888 *)
- FOR i := 1 TO width DO
- S.GET( bp + 3, byte ); S.PUT( ip, byte ); INC( ip ); (* X *)
- S.GET( bp + 2, byte ); S.PUT( ip, byte ); INC( ip ); (* B *)
- S.GET( bp + 1, byte ); S.PUT( ip, byte ); INC( ip ); (* G *)
- S.GET( bp + 0, byte ); S.PUT( ip, byte ); INC( ip ); (* R *)
- INC( bp, 4 );
- END;
- END;
- END PutLineBE;
- PROCEDURE GetLineBE( xformat, width: LONGINT; ip, bp: ADDRESS );
- VAR i: LONGINT; byte: CHAR;
- BEGIN
- CASE xformat OF
- | index8:
- FOR i := 1 TO width DO
- S.GET( ip, byte ); S.PUT( bp, byte ); INC( ip ); INC( bp )
- END
- | color565, color555, color664:
- FOR i := 1 TO width DO
- S.GET( ip, byte ); S.PUT( bp + 1, byte ); INC( ip );
- S.GET( ip, byte ); S.PUT( bp + 0, byte ); INC( ip );
- INC( bp, 2 )
- END
- | color888:
- FOR i := 1 TO width DO
- INC( ip );
- S.GET( ip, byte ); S.PUT( bp + 2, byte ); INC( ip ); (* B *)
- S.GET( ip, byte ); S.PUT( bp + 1, byte ); INC( ip ); (* G *)
- S.GET( ip, byte ); S.PUT( bp + 0, byte ); INC( ip ); (* R *)
- INC( bp, 3 )
- END;
- ELSE (* color8888 *)
- FOR i := 1 TO width DO
- S.GET( ip, byte ); S.PUT( bp + 3, byte ); INC( ip ); (* X *)
- S.GET( ip, byte ); S.PUT( bp + 2, byte ); INC( ip ); (* B *)
- S.GET( ip, byte ); S.PUT( bp + 1, byte ); INC( ip ); (* G *)
- S.GET( ip, byte ); S.PUT( bp + 0, byte ); INC( ip ); (* R *)
- INC( bp, 4 )
- END;
- END;
- END GetLineBE;
- PROCEDURE NewPattern( d: Display;
- CONST image: ARRAY OF SET;
- width, height: INTEGER ): X11.Pattern;
- VAR
- pixmap: X11.Pixmap; pat: X11.PatternPtr;
- w, h, i, j, b, dest, srcw, destb, srci, desti: LONGINT;
- data: ARRAY 256*32 OF CHAR; (* 256*256 bits *)
- BEGIN
- i := 0;
- WHILE i < LEN( data ) DO data[i] := 0X; INC( i ) END;
- w := width; h := height;
- srcw := (width + 31) DIV 32; (* number of words in source line *)
- destb := (w + 7) DIV 8; (* number of bytes in dest line *)
- srci := (height - 1)*srcw; desti := 0;
- WHILE srci >= 0 DO
- i := 0; j := 0; b := 0; dest := 0;
- LOOP
- dest := dest DIV 2;
- IF b IN image[srci + j + 1] THEN INC( dest, 80H ) END;
- INC( b );
- IF b MOD 8 = 0 THEN
- data[desti + i] := CHR( dest ); INC( i ); dest := 0;
- IF i >= destb THEN EXIT END
- END;
- IF b = 32 THEN
- b := 0; INC( j );
- IF j >= srcw THEN
- WHILE i < destb DO data[desti + i] := 0X; INC( i ) END;
- EXIT
- END
- END
- END;
- INC( desti, destb ); DEC( srci, srcw )
- END;
- Machine.Acquire( Machine.X11 );
- pixmap := X11.CreateBitmapFromData( d.xdisp, d.primary, ADDRESSOF( data[0] ), w, h );
- Machine.Release( Machine.X11 );
- IF pixmap = 0 THEN HALT( 99 ) END;
- pat := S.VAL( X11.PatternPtr, Unix.malloc( SIZEOF( X11.PatternDesc ) ) );
- pat.x := 0; pat.y := 0; pat.w := width; pat.h := height; pat.pixmap := pixmap;
- RETURN S.VAL( LONGINT, pat )
- END NewPattern;
- PROCEDURE InitNames;
- VAR cwd: ARRAY 128 OF CHAR; i: LONGINT;
- BEGIN
- UnixFiles.GetWorkingDirectory( cwd );
- COPY( Machine.version, winName );
- Strings.Append( winName, ", Work: " ); Strings.Append( winName, cwd );
- COPY( winName, iconName);
- i := 0;
- WHILE iconName[i] > ' ' DO INC( i ) END;
- iconName[i] := 0X
- END InitNames;
- PROCEDURE getDisplayName;
- VAR adr: ADDRESS; i: INTEGER; ch: CHAR;
- BEGIN
- Unix.GetArgval( "-display", dispname );
- IF dispname = "" THEN
- adr := Unix.getenv( ADDRESSOF( "DISPLAY" ) );
- IF adr # 0 THEN
- i := 0;
- REPEAT S.GET( adr, ch ); INC( adr ); dispname[i] := ch; INC( i ) UNTIL ch = 0X;
- ELSE dispname := ":0"
- END
- END
- END getDisplayName;
- PROCEDURE OpenX11Display( ): X11.DisplayPtr;
- VAR xdisp: X11.DisplayPtr; screen, depth: LONGINT;
- BEGIN
- getDisplayName;
- xdisp := Api.OpenDisplay( dispname );
- IF xdisp = 0 THEN
- Trace.String( "Cannot open X11 display " ); Trace.StringLn( dispname ); Unix.exit( 1 )
- END;
- screen := X11.DefaultScreen( xdisp );
- depth := X11.DefaultDepth( xdisp, screen );
- IF depth < 8 THEN
- Trace.StringLn( "UnixAos needs a color display. sorry." ); Unix.exit( 1 )
- END;
- Trace.String( "X11 Display depth = " ); Trace.Int( depth, 1 ); Trace.Ln;
- RETURN xdisp
- END OpenX11Display;
- PROCEDURE CreateColors( d: Display );
- VAR col: INTEGER;
- visualInfo: X11.VisualInfo;
- BEGIN
- Machine.Acquire( Machine.X11 );
- col := 0;
- WHILE col < 256 DO d.pixel[col] := col; INC( col ) END;
- IF (d.depth > 8) & (X11.MatchVisualInfo( d.xdisp, d.screen, d.depth, X11.TrueColor, visualInfo ) = 1) THEN
- d.visual := visualInfo.visual;
- ELSIF X11.MatchVisualInfo( d.xdisp, d.screen, d.depth, X11.PseudoColor, visualInfo ) = 1 THEN
- d.visual := visualInfo.visual
- END;
- d.bigEndian := FALSE;
- IF d.depth > 8 THEN
- d.bigEndian := d.visual.blueMask > d.visual.redMask
- ELSE (* pseudo color *)
- d.cmap := X11.CreateColormap( d.xdisp, d.primary, d.visual, X11.AllocAll );
- X11.SetWindowColormap( d.xdisp, d.primary, d.cmap );
- d.foreground := d.pixel[FG];
- d.background := d.pixel[BG];
- X11.SetWindowBackground( d.xdisp, d.primary, d.background );
- X11.ClearWindow( d.xdisp, d.primary )
- END;
- Machine.Release( Machine.X11 );
- d.planesMask := ASH( 1, d.depth ) - 1
- END CreateColors;
- PROCEDURE InitPalette( d: Display );
- VAR f: Files.File; r: Files.Reader; red, green, blue: CHAR; i, cols: INTEGER;
- BEGIN
- IF d.depth >= 8 THEN cols := 256 ELSE cols := 16 END;
- f := Files.Old( "Default.Pal" );
- IF f # NIL THEN
- Files.OpenReader( r, f, 0 );
- FOR i := 0 TO cols - 1 DO
- r.Char( red ); r.Char( green ); r.Char( blue );
- d.SetColor( i, ORD( red ), ORD( green ), ORD( blue ) )
- END
- END;
- d.defPal := d.rgb
- END InitPalette;
- PROCEDURE SuppressX11Cursors( d: Display );
- VAR
- fg, bg: X11.Color; src, msk: X11.PatternPtr;
- image: ARRAY 17 OF SET; i: INTEGER;
- noCursor: X11.Cursor;
- BEGIN
- fg.red := 256*d.rgb[FG].r; fg.green := 256*d.rgb[FG].g; fg.blue := 256*d.rgb[FG].b;
- bg.red := 256*d.rgb[BG].r; bg.green := 256*d.rgb[BG].g; bg.blue := 256*d.rgb[BG].b;
- FOR i := 1 TO 16 DO image[i] := {} END;
- src := S.VAL( X11.PatternPtr, NewPattern( d, image, 16, 16 ) );
- msk := S.VAL( X11.PatternPtr, NewPattern( d, image, 16, 16 ) );
-
- Machine.Acquire( Machine.X11 );
- noCursor := X11.CreatePixmapCursor( d.xdisp, src.pixmap, msk.pixmap, fg, bg, 1, 1 );
- X11.DefineCursor( d.xdisp, d.primary, noCursor );
- Machine.Release( Machine.X11 )
- END SuppressX11Cursors;
-
- PROCEDURE InitFormat( d: Display );
- BEGIN
- IF d.depth = 8 THEN
- d.format := Displays.index8;
- d.xformat := index8
- ELSIF d.depth = 15 THEN
- d.format := Displays.color565;
- d.xformat := color555
- ELSIF d.depth = 16 THEN
- d.format := Displays.color565;
- IF d.visual.blueMask = 0FH THEN d.xformat := color664
- ELSE d.xformat := color565
- END
- ELSIF d.depth = 24 THEN
- d.format := Displays.color8888;
- d.xformat := color888
- ELSIF d.depth = 32 THEN
- d.format := Displays.color8888;
- d.xformat := color8888
- ELSE
- d.format := unknown
- END;
- END InitFormat;
- PROCEDURE CreateGC( d: Display );
- BEGIN
- Machine.Acquire( Machine.X11 );
- d.gc := X11.CreateGC( d.xdisp, d.primary, 0, 0 );
- IF d.gc = 0 THEN Machine.Release( Machine.X11 ); HALT( 45 ) END;
- X11.SetPlaneMask( d.xdisp, d.gc, d.planesMask );
- X11.SetGraphicsExposures( d.xdisp, d.gc, X11.True );
- X11.SetBackground( d.xdisp, d.gc, d.background );
- Machine.Release( Machine.X11 );
- END CreateGC;
- PROCEDURE InitFunctions( d: Display );
- BEGIN
- d.xfunc[replace] := X11.GXcopy;
- d.xfunc[paint] := X11.GXor; (* not used *)
- (* drawing in invert mode with BackgroundCol on BackgroundCol is a no-op: *)
- IF S.VAL( SET, d.background )*S.VAL( SET, d.planesMask ) # {} THEN
- d.xfunc[invert] := X11.GXequiv
- ELSE
- d.xfunc[invert] := X11.GXxor
- END;
- d.currcol := -1; d.currmode := -1;
- END InitFunctions;
- (* PB - 2010-04-20
- Return:
- -1: absolute width and height according to DisplaySize config string.
- else: value from 50 to 100 as scaling factor, argument variables width and height are unspecified.
- Lower limit is either 50% as scaling factor or 640x480 as absolute size.
- *)
- PROCEDURE GetDisplaySize(VAR width, height: LONGINT): LONGINT; (* % of Screen [50% ... 100%] *)
- VAR buf: ARRAY 64 OF CHAR; size, i: LONGINT; c: CHAR; absolute: BOOLEAN;
- BEGIN
- Machine.GetConfig( "DisplaySize", buf );
- IF buf = "" THEN size := 100
- ELSE
- size := 0; c := buf[0]; i := 0;
- WHILE (c >= '0') & (c <= '9') DO
- size := 10*size + ORD( c ) - ORD( '0' );
- INC( i ); c := buf[i]
- END;
- IF c = 'x' THEN
- width := size;
- size := 0;
- INC( i ); c := buf[i];
- END;
- WHILE (c >= '0') & (c <= '9') DO
- size := 10*size + ORD( c ) - ORD( '0' );
- INC( i ); c := buf[i]
- END;
- IF (width # 0) & (size # 0) THEN
- height := size;
- absolute := TRUE;
- ELSIF (width # 0) THEN (* failed to read two numbers -> fall back to scaling *)
- size := width;
- width := 0
- END;
- IF absolute THEN
- size := -1;
- IF width < 640 THEN width := 640; END;
- IF height < 480 THEN height := 480; END;
- ELSE
- IF size < 50 THEN size := 50 END;
- IF size > 100 THEN size := 100 END
- END;
- END;
- RETURN size
- END GetDisplaySize;
- PROCEDURE Install*;
- VAR disp: Display; res: LONGINT; s, w, h: LONGINT; xdisp: X11.DisplayPtr;
- BEGIN
- InitNames; xdisp := OpenX11Display( );
- s := GetDisplaySize( w, h );
- NEW( disp, xdisp, w, h, s, s );
- disp.SetName( "XDisplay" );
- disp.desc := "X11 display driver";
- Displays.registry.Add( disp, res );
- END Install;
- BEGIN
- NEW( imgBuffer, 10000 )
- END XDisplay.
|