Unix.XDisplay.Mod 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. (* ETH Oberon, Copyright 2000 ETH Zürich Institut für Computersysteme, ETH Zentrum, CH-8092 Zürich.
  2. Refer to the general ETH Oberon System license contract available at: http://www.oberon.ethz.ch/ *)
  3. MODULE XDisplay; (** AUTHOR "gf"; PURPOSE "display driver plugin for X Windows *)
  4. IMPORT S := SYSTEM, Trace, Unix, Machine, Files, UnixFiles, X11, Api := X11Api, Displays, Strings;
  5. CONST
  6. BG = 0; FG = 15; (* Background, foreground colors.*)
  7. CONST
  8. (* formats for Transfer. value DIV 8 = bytes per pixel. *)
  9. unknown = 0;
  10. index8 = 8; color555 = 16; color565 = 17; color664 = 18;
  11. color888 = 24; color8888* = 32;
  12. (* Drawing operation modes. *)
  13. replace = 0; (* destcolor := sourcecolor. *)
  14. paint = 1; (* destcolor := destcolor OR sourcecolor. *)
  15. invert = 2; (* destcolor := destcolor XOR sourcecolor. *)
  16. VAR
  17. winName, iconName: ARRAY 128 OF CHAR;
  18. TYPE
  19. RGB = RECORD
  20. r, g, b: INTEGER
  21. END;
  22. Clip* = OBJECT
  23. VAR
  24. d: Display; lx, ly, lw, lh: LONGINT;
  25. PROCEDURE & Init( disp: Display );
  26. BEGIN
  27. d := disp; lx := 0; ly := 0; lw := 0; lh := 0;
  28. Reset
  29. END Init;
  30. PROCEDURE Set*( x, y, w, h: LONGINT );
  31. VAR rect: X11.Rectangle;
  32. BEGIN
  33. IF w < 0 THEN w := 0 END;
  34. IF h < 0 THEN h := 0 END;
  35. IF (x # lx) OR (y # ly) OR (w # lw) OR (h # lh) THEN
  36. lx := x; ly := y; lw := w; lh := h;
  37. IF y < d.height THEN d.currwin := d.primary ELSE d.currwin := d.secondary; DEC( y, d.height ) END;
  38. rect.x := SHORT( x ); rect.y := SHORT( y );
  39. rect.w := SHORT( w ); rect.h := SHORT( h );
  40. Machine.Acquire( Machine.X11 );
  41. IF (rect.x <= 0) & (rect.y <= 0) & (rect.w >= d.width) & (rect.h >= d.height) THEN
  42. X11.SetClipMask( d.xdisp, d.gc, X11.None ) (* no clipping *)
  43. ELSE
  44. X11.SetClipRectangles( d.xdisp, d.gc, 0, 0, ADDRESSOF( rect ), 1, X11.YXBanded )
  45. END;
  46. Machine.Release( Machine.X11 )
  47. END;
  48. END Set;
  49. PROCEDURE Get*( VAR x, y, w, h: LONGINT );
  50. BEGIN
  51. x := lx; y := ly; w := lw; h := lh
  52. END Get;
  53. PROCEDURE InClip*( x, y, w, h: LONGINT ): BOOLEAN;
  54. BEGIN
  55. RETURN (x >= lx) & (x + w <= lx + lw) & (y >= ly) & (y + h <= ly + lh)
  56. END InClip;
  57. PROCEDURE Reset*;
  58. BEGIN
  59. Set( 0, 0, d.width, d.height );
  60. END Reset;
  61. (** Intersect with current clip rectangle resulting in a new clip rectangle. *)
  62. PROCEDURE Adjust*( x, y, w, h: LONGINT ); (* intersection *)
  63. VAR x0, y0, x1, y1: LONGINT;
  64. BEGIN
  65. IF x > lx THEN x0 := x ELSE x0 := lx END;
  66. IF y > ly THEN y0 := y ELSE y0 := ly END;
  67. IF x + w < lx + lw THEN x1 := x + w ELSE x1 := lx + lw END;
  68. IF y + h < ly + lh THEN y1 := y + h ELSE y1 := ly + lh END;
  69. Set( x0, y0, x1 - x0, y1 - y0 );
  70. END Adjust;
  71. END Clip;
  72. Display* = OBJECT (Displays.Display)
  73. VAR
  74. xdisp- : X11.DisplayPtr;
  75. primary- : X11.Window;
  76. secondary- : X11.Window;
  77. currwin : X11.Window;
  78. wmDelete- : X11.Atom;
  79. screen : LONGINT;
  80. visual{UNTRACED} : X11.VisualPtr;
  81. depth : LONGINT;
  82. bigEndian : BOOLEAN;
  83. gc : X11.GC;
  84. clip : Clip;
  85. cmap : X11.Colormap;
  86. planesMask : LONGINT;
  87. foreground,
  88. background : LONGWORD;
  89. rgb, defPal : ARRAY 256 OF RGB; (* 8-bit pseudo color *)
  90. pixel : ARRAY 256 OF LONGINT; (* pixel values for Oberon colors *)
  91. xformat : LONGINT;
  92. currcol, currmode : LONGINT;
  93. xfunc : ARRAY 3 OF LONGINT;
  94. PROCEDURE SetMode( col: LONGINT );
  95. VAR mode: LONGINT;
  96. BEGIN
  97. mode := replace;
  98. IF (col # -1) & (30 IN S.VAL( SET, col )) THEN mode := invert; EXCL( S.VAL( SET, col ), 30 ) END;
  99. IF mode # currmode THEN X11.SetFunction( xdisp, gc, xfunc[mode] ); currmode := mode END;
  100. IF col # currcol THEN X11.SetForeground( xdisp, gc, ColorToPixel( col ) ); currcol := col END;
  101. END SetMode;
  102. PROCEDURE Dot*( col, x, y: LONGINT );
  103. BEGIN
  104. IF currwin = secondary THEN DEC( y, height ) END;
  105. Machine.Acquire( Machine.X11 );
  106. SetMode( col );
  107. X11.DrawPoint( xdisp, currwin, gc, x, y );
  108. Machine.Release( Machine.X11 )
  109. END Dot;
  110. PROCEDURE Fill*( col, x, y, w, h: LONGINT );
  111. BEGIN
  112. IF (h > 0) & (w > 0) THEN
  113. IF currwin = secondary THEN DEC( y, height ) END;
  114. Machine.Acquire( Machine.X11 );
  115. SetMode( col );
  116. X11.FillRectangle( xdisp, currwin, gc, x, y, w, h );
  117. Machine.Release( Machine.X11 )
  118. END
  119. END Fill;
  120. (** Transfer a block of pixels in "raw" display format to (op = set) or from (op = get) the display.
  121. Pixels in the rectangular area are transferred from left to right and top to bottom. The pixels
  122. are transferred to or from "buf", starting at "ofs". The line byte increment is "stride", which may
  123. be positive, negative or zero. *)
  124. PROCEDURE Transfer*( VAR buf: ARRAY OF CHAR; ofs, stride, x, y, w, h, op: LONGINT );
  125. CONST Get = 0; Set = 1;
  126. VAR image: X11.Image;
  127. imp: X11.ImagePtr;
  128. bp, ip: ADDRESS;
  129. line, ll: LONGINT;
  130. BEGIN
  131. ll := w*(xformat DIV 8);
  132. IF (ofs + (h - 1)*stride + ll > LEN( buf )) OR (ofs + (h - 1)*stride < 0) THEN HALT( 99 ) END;
  133. IF LEN( imgBuffer ) < 4*w*h THEN
  134. NEW( imgBuffer, 4*w*h ); (* create buffer outside lock to avoid deadlock *)
  135. END;
  136. bp := ADDRESSOF( buf[ofs] );
  137. IF op = Set THEN
  138. Machine.Acquire( Machine.X11 );
  139. image := X11.CreateImage( xdisp, visual, depth, X11.ZPixmap, 0, 0, w, h, 32, 0 );
  140. imp := S.VAL( X11.ImagePtr, image );
  141. imp.data := ADDRESSOF( imgBuffer[0] ); ip := imp.data;
  142. IF imp.byteOrder = 0 THEN
  143. FOR line := 0 TO h - 1 DO
  144. PutLine( xformat, w, ip, bp );
  145. INC( bp, stride ); INC( ip, imp.bytesPerLine )
  146. END;
  147. ELSE
  148. FOR line := 0 TO h - 1 DO
  149. PutLineBE( xformat, w, ip, bp );
  150. INC( bp, stride ); INC( ip, imp.bytesPerLine )
  151. END;
  152. END;
  153. IF currmode # replace THEN
  154. X11.SetFunction( xdisp, gc, xfunc[replace] ); currmode := replace
  155. END;
  156. X11.PutImage( xdisp, primary, gc, image, 0, 0, x, y, w, h );
  157. X11.Free( image ); imp := NIL;
  158. Machine.Release( Machine.X11 )
  159. ELSIF op = Get THEN
  160. Machine.Acquire( Machine.X11 );
  161. image := X11.GetImage( xdisp, primary, x, y, w, h, planesMask, X11.ZPixmap );
  162. imp := S.VAL( X11.ImagePtr, image ); ip := imp.data;
  163. IF imp.byteOrder = 0 THEN
  164. FOR line := 0 TO h - 1 DO
  165. GetLine( xformat, w, ip, bp );
  166. INC( bp, stride ); INC( ip, imp.bytesPerLine )
  167. END
  168. ELSE
  169. FOR line := 0 TO h - 1 DO
  170. GetLineBE( xformat, w, ip, bp );
  171. INC( bp, stride ); INC( ip, imp.bytesPerLine )
  172. END
  173. END;
  174. X11.Free( imp.data ); X11.Free( image ); imp := NIL;
  175. Machine.Release( Machine.X11 )
  176. END;
  177. END Transfer;
  178. (** Transfer a block of pixels from a 1-bit mask to the display. Pixels in the rectangular area are
  179. transferred from left to right and top to bottom. The pixels are transferred from "buf", starting
  180. at bit offset "bitofs". The line byte increment is "stride", which may be positive, negative or zero.
  181. "fg" and "bg" specify the colors for value 1 and 0 pixels respectively. *)
  182. PROCEDURE Mask*( VAR buf: ARRAY OF CHAR; bitofs, stride, fg, bg, x, y, w, h: LONGINT );
  183. VAR p: ADDRESS; i: LONGINT; s: SET;
  184. image: X11.Image;
  185. fgpixel, bgpixel, xret: LONGINT;
  186. ix, iy, ih: LONGINT;
  187. imp: X11.ImagePtr;
  188. BEGIN
  189. IF (w > 0) & (h > 0) THEN
  190. IF fg >= 0 THEN fgpixel := pixel[fg MOD 256] ELSE fgpixel := ColorToPixel( fg ) END;
  191. IF bg >= 0 THEN bgpixel := pixel[bg MOD 256] ELSE bgpixel := ColorToPixel( bg ) END;
  192. IF LEN( imgBuffer ) < 4*w*h THEN
  193. NEW( imgBuffer, 4*w*h ); (* create buffer outside lock to avoid deadlock *)
  194. END;
  195. Machine.Acquire( Machine.X11 );
  196. image := X11.CreateImage( xdisp, visual, depth, X11.ZPixmap, 0, 0, w, h, 32, 0 );
  197. imp := S.VAL( X11.ImagePtr, image );
  198. imp.data := ADDRESSOF( imgBuffer[0] );
  199. i := LONGINT(ADDRESSOF( buf[0] ) MOD 4); INC( bitofs, i*8 );
  200. p := ADDRESSOF( buf[0] ) - i + bitofs DIV 32*4; (* p always aligned to 32-bit boundary *)
  201. bitofs := bitofs MOD 32; stride := stride*8;
  202. ix := 0; iy := 0; ih := h;
  203. LOOP
  204. S.GET( p, s ); i := bitofs;
  205. LOOP
  206. IF (i MOD 32) IN s THEN xret := X11.PutPixel( image, ix, iy, fgpixel );
  207. ELSE xret := X11.PutPixel( image, ix, iy, bgpixel );
  208. END;
  209. INC( i ); INC( ix );
  210. IF i - bitofs = w THEN EXIT END;
  211. IF i MOD 32 = 0 THEN S.GET( p + i DIV 8, s ) END
  212. END;
  213. DEC( ih );
  214. IF ih = 0 THEN EXIT END;
  215. INC( iy ); ix := 0; INC( bitofs, stride );
  216. IF (bitofs >= 32) OR (bitofs < 0) THEN (* moved outside s *)
  217. INC( p, bitofs DIV 32*4 ); bitofs := bitofs MOD 32
  218. END
  219. END; (* loop *)
  220. IF currmode # replace THEN X11.SetFunction( xdisp, gc, xfunc[replace] ) END;
  221. X11.PutImage( xdisp, primary, gc, image, 0, 0, x, y, w, h );
  222. IF currmode # replace THEN X11.SetFunction( xdisp, gc, xfunc[currmode] ) END;
  223. X11.Free( image );
  224. Machine.Release( Machine.X11 );
  225. END
  226. END Mask;
  227. (** Copy source block sx, sy, w, h to destination dx, dy. Overlap is allowed. *)
  228. PROCEDURE Copy*( sx, sy, w, h, dx, dy: LONGINT );
  229. VAR src: X11.DisplayPtr;
  230. BEGIN
  231. IF (w > 0) & (h > 0) THEN
  232. IF sy < height THEN src := primary ELSE src := secondary; DEC( sy, height ) END;
  233. IF currwin = secondary THEN DEC( sy, height ) END;
  234. Machine.Acquire( Machine.X11 );
  235. SetMode( currcol );
  236. X11.CopyArea( xdisp, src, currwin, gc, sx, sy, w, h, dx, dy );
  237. Machine.Release( Machine.X11 )
  238. END;
  239. END Copy;
  240. (** Update the visible display (if caching is used). *)
  241. PROCEDURE Update*;
  242. BEGIN
  243. Machine.Acquire( Machine.X11 );
  244. X11.Sync( xdisp, X11.False );
  245. Machine.Release( Machine.X11 )
  246. END Update;
  247. (** Map a color value to an 8-bit CLUT index. Only used if xformat = index8. *)
  248. PROCEDURE ColorToIndex*( col: LONGINT ): LONGINT;
  249. BEGIN
  250. RETURN ColorToIndex0( SELF, col )
  251. END ColorToIndex;
  252. (** Map an 8-bit CLUT index to a color value. Only used if xformat = index8. *)
  253. PROCEDURE IndexToColor*( n: LONGINT ): LONGINT;
  254. VAR r, g, b: LONGINT;
  255. BEGIN
  256. IF n >= 0 THEN
  257. IF n > 255 THEN n := BG END;
  258. r := rgb[n].r; g := rgb[n].g; b := rgb[n].b;
  259. RETURN MIN( LONGINT ) + (r*100H + g)*100H + b
  260. ELSE RETURN n
  261. END;
  262. END IndexToColor;
  263. PROCEDURE SetColor*( col, red, green, blue: INTEGER ); (* 0 <= col, red, green, blue < 256 *)
  264. VAR xcol: X11.Color; res: LONGINT;
  265. BEGIN
  266. IF (col < 0) OR (col > 255) THEN RETURN END;
  267. rgb[col].r := red; rgb[col].g := green; rgb[col].b := blue;
  268. xcol.red := 256*red; xcol.green := 256*green; xcol.blue := 256*blue;
  269. Machine.Acquire( Machine.X11 );
  270. IF depth > 8 THEN
  271. res := X11.AllocColor( xdisp, cmap, ADDRESSOF( xcol ) );
  272. IF res # 0 THEN pixel[col] := LONGINT (xcol.pixel) END
  273. ELSE
  274. xcol.flags := CHR( X11.DoAll ); xcol.pixel := pixel[col];
  275. X11.StoreColor( xdisp, cmap, ADDRESSOF( xcol ) )
  276. END;
  277. Machine.Release( Machine.X11 )
  278. END SetColor;
  279. PROCEDURE GetColor*( col: INTEGER; VAR red, green, blue: INTEGER );
  280. BEGIN
  281. IF (0 <= col) & (col <= 255) THEN
  282. red := rgb[col].r; green := rgb[col].g; blue := rgb[col].b
  283. ELSE
  284. red := rgb[BG].r; green := rgb[BG].g; blue := rgb[BG].b
  285. END
  286. END GetColor;
  287. PROCEDURE ColorToPixel*( col: LONGINT ): LONGINT;
  288. VAR r, g, b, i, ii, x, y, z, m, min: LONGINT; rc: RGB;
  289. BEGIN
  290. r := LSH( col, -16 ) MOD 256; g := LSH( col, -8 ) MOD 256; b := col MOD 256;
  291. CASE xformat OF
  292. color8888, color888:
  293. IF bigEndian THEN RETURN ASH( b, 16 ) + ASH( g, 8 ) + r
  294. ELSE RETURN ASH( r, 16 ) + ASH( g, 8 ) + b
  295. END
  296. | color555:
  297. r := 32*r DIV 256; g := 32*g DIV 256; b := 32*b DIV 256;
  298. IF bigEndian THEN RETURN ASH( b, 10 ) + ASH( g, 5 ) + r
  299. ELSE RETURN ASH( r, 10 ) + ASH( g, 5 ) + b
  300. END
  301. | color565:
  302. r := 32*r DIV 256; g := 64*g DIV 256; b := 32*b DIV 256;
  303. IF bigEndian THEN RETURN ASH( b, 11 ) + ASH( g, 5 ) + r
  304. ELSE RETURN ASH( r, 11 ) + ASH( g, 5 ) + b
  305. END
  306. | color664:
  307. r := 64*r DIV 256; g := 64*g DIV 256; b := 16*b DIV 256;
  308. IF bigEndian THEN RETURN ASH( b, 12 ) + ASH( g, 6 ) + r
  309. ELSE RETURN ASH( r, 10 ) + ASH( g, 4 ) + b
  310. END
  311. ELSE (* index8 *)
  312. i := 0; ii := 0; min := MAX( LONGINT );
  313. WHILE (i < 256) & (min > 0) DO
  314. rc := rgb[i];
  315. x := ABS( r - rc.r ); y := ABS( g - rc.g ); z := ABS( b - rc.b ); m := x;
  316. IF y > m THEN m := y END;
  317. IF z > m THEN m := z END;
  318. m := m*m + (x*x + y*y + z*z);
  319. IF m < min THEN min := m; ii := i END;
  320. INC( i )
  321. END;
  322. RETURN pixel[ii]
  323. END
  324. END ColorToPixel;
  325. PROCEDURE & Initialize( disp: X11.DisplayPtr; absWidth, absHeight, relWidth, relHeight: LONGINT );
  326. VAR
  327. event: Api.XEvent; root: X11.Window;
  328. gRoot, gX, gY, gW, gH, gBW, gD, res: LONGINT; screenw, screenh : LONGINT;
  329. BEGIN
  330. xdisp := disp;
  331. screen := X11.DefaultScreen( xdisp );
  332. screenw := X11.DisplayWidth( xdisp, screen );
  333. screenh := X11.DisplayHeight( xdisp, screen );
  334. depth := X11.DefaultDepth( xdisp, screen );
  335. cmap := X11.DefaultColormap( xdisp, screen );
  336. foreground := X11.BlackPixel( xdisp, screen );
  337. background := X11.WhitePixel( xdisp, screen );
  338. Machine.Acquire( Machine.X11 );
  339. root := X11.DefaultRootWindow( xdisp );
  340. primary := X11.CreateSimpleWindow( xdisp, root, 0, 0,
  341. screenw - 16, screenh - 32, 0,
  342. foreground, background );
  343. X11.StoreName( xdisp, primary, ADDRESSOF( winName ) );
  344. X11.SetIconName( xdisp, primary, ADDRESSOF( iconName ) );
  345. X11.SetCommand( xdisp, primary, Unix.argv, Unix.argc );
  346. X11.SelectInput( xdisp, primary, X11.ExposureMask );
  347. (* set wm_delete_events if in windowed mode *)
  348. wmDelete := Api.InternAtom(xdisp, "WM_DELETE_WINDOW", Api.True);
  349. res := Api.SetWMProtocols(xdisp, primary, ADDRESSOF(wmDelete), 1);
  350. X11.MapRaised( xdisp, primary );
  351. REPEAT Api.NextEvent( xdisp, event )
  352. UNTIL (event.typ = Api.Expose) & (event.window = primary);
  353. (* adjust to physical window size *)
  354. X11.GetGeometry( xdisp, primary, gRoot, gX, gY, gW, gH, gBW, gD );
  355. IF relWidth # -1 THEN
  356. gW := relWidth * gW DIV 100;
  357. ELSE
  358. gW := absWidth;
  359. END;
  360. IF relHeight # -1 THEN
  361. gH := relHeight * gH DIV 100;
  362. ELSE
  363. gH := absHeight;
  364. END;
  365. IF gW MOD 8 # 0 THEN DEC( gW, gW MOD 8 ) END;
  366. X11.ResizeWindow( xdisp, primary, gW, gH );
  367. width := gW; height := gH;
  368. offscreen := height;
  369. (* pixmap may not be larger than screen: *)
  370. IF gW > screenw THEN gW := screenw END;
  371. IF gH > screenh THEN gH := screenh END;
  372. secondary := X11.CreatePixmap( xdisp, primary, gW, gH, depth );
  373. Machine.Release( Machine.X11 );
  374. CreateColors( SELF ); InitPalette( SELF ); SuppressX11Cursors( SELF );
  375. InitFormat( SELF ); CreateGC( SELF ); InitFunctions( SELF );
  376. NEW( clip, SELF )
  377. END Initialize;
  378. (** Finalize the display. Further calls to display methods are not allowed, and may cause exceptions. *)
  379. PROCEDURE Finalize*;
  380. (*
  381. BEGIN (* should really be exclusive with Transfer, but we assume the caller keeps to the rules above *)
  382. fbadr := 0; fbsize := 0
  383. *)
  384. END Finalize;
  385. END Display;
  386. VAR
  387. dispname: ARRAY 128 OF CHAR;
  388. imgBuffer: POINTER TO ARRAY OF CHAR;
  389. PROCEDURE ColorToIndex0( disp: Display; col: LONGINT ): INTEGER;
  390. VAR idx, i: INTEGER; r, g, b, min, x, y, z, d: LONGINT; rc: RGB;
  391. BEGIN
  392. r := ASH( col, -16 ) MOD 100H; g := ASH( col, -8 ) MOD 100H; b := col MOD 100H;
  393. i := 0; idx := 0; min := MAX( LONGINT );
  394. WHILE (i < 256) & (min > 0) DO
  395. rc := disp.defPal[i]; x := ABS( r - rc.r ); y := ABS( g - rc.g ); z := ABS( b - rc.b ); d := x;
  396. IF y > d THEN d := y END;
  397. IF z > d THEN d := z END;
  398. d := d*d + (x*x + y*y + z*z);
  399. IF d < min THEN min := d; idx := i END;
  400. INC( i )
  401. END;
  402. RETURN idx
  403. END ColorToIndex0;
  404. PROCEDURE PutLine( xformat, width: LONGINT; ip, bp: ADDRESS );
  405. VAR i: LONGINT; byte: CHAR;
  406. BEGIN
  407. CASE xformat OF
  408. | index8:
  409. S.MOVE(bp, ip, width);
  410. | color565, color555, color664:
  411. S.MOVE(bp, ip, 2*width);
  412. | color888: (* x-format (destination) is 888, A ignored (?) , Aos Format (source) is 8888 *)
  413. S.MOVE(bp, ip, 4*width);
  414. (*
  415. FOR i := 1 TO width DO
  416. S.MOVE(bp,ip,3); INC(bp,3); INC(ip,3);
  417. (*
  418. S.GET( bp, byte ); S.PUT( ip, byte ); INC( bp ); INC( ip ); (* B *)
  419. S.GET( bp, byte ); S.PUT( ip, byte ); INC( bp ); INC( ip ); (* G *)
  420. S.GET( bp, byte ); S.PUT( ip, byte ); INC( bp ); INC( ip ); (* R *)
  421. *)
  422. byte := 0X; S.PUT( ip, byte ); INC( ip )
  423. END;
  424. *)
  425. ELSE (* color8888 *)
  426. S.MOVE(bp, ip, 4*width);
  427. END
  428. END PutLine;
  429. PROCEDURE GetLine( xformat, width: LONGINT; ip, bp: ADDRESS );
  430. VAR i: LONGINT; byte: CHAR;
  431. BEGIN
  432. CASE xformat OF
  433. | index8:
  434. S.MOVE(ip, bp, width);
  435. | color565, color555, color664:
  436. S.MOVE(ip, bp, 2*width);
  437. | color888:
  438. S.MOVE(ip, bp, 4*width);
  439. (*
  440. FOR i := 1 TO width DO
  441. S.GET( ip, byte ); S.PUT( bp, byte ); INC( ip ); INC( bp ); (* B *)
  442. S.GET( ip, byte ); S.PUT( bp, byte ); INC( ip ); INC( bp ); (* G *)
  443. S.GET( ip, byte ); S.PUT( bp, byte ); INC( ip ); INC( bp ); (* R *)
  444. INC( ip )
  445. END
  446. *)
  447. ELSE (* color8888 *)
  448. S.MOVE(ip, bp, 4*width);
  449. END;
  450. END GetLine;
  451. PROCEDURE PutLineBE( xformat, width: LONGINT; ip, bp: ADDRESS );
  452. VAR i: LONGINT; byte: CHAR;
  453. BEGIN
  454. CASE xformat OF
  455. index8:
  456. FOR i := 1 TO width DO
  457. S.GET( bp, byte ); S.PUT( ip, byte ); INC( bp ); INC( ip )
  458. END
  459. | color565, color555, color664:
  460. FOR i := 1 TO width DO
  461. S.GET( bp + 1, byte ); S.PUT( ip, byte ); INC( ip );
  462. S.GET( bp + 0, byte ); S.PUT( ip, byte ); INC( ip );
  463. INC( bp, 2 )
  464. END
  465. | color888:
  466. FOR i := 1 TO width DO
  467. S.PUT8( ip, 0X ); INC( ip );
  468. S.GET( bp + 2, byte ); S.PUT( ip, byte ); INC( ip ); (* B *)
  469. S.GET( bp + 1, byte ); S.PUT( ip, byte ); INC( ip ); (* G *)
  470. S.GET( bp + 0, byte ); S.PUT( ip, byte ); INC( ip ); (* R *)
  471. INC( bp, 4 )
  472. END
  473. ELSE (* color8888 *)
  474. FOR i := 1 TO width DO
  475. S.GET( bp + 3, byte ); S.PUT( ip, byte ); INC( ip ); (* X *)
  476. S.GET( bp + 2, byte ); S.PUT( ip, byte ); INC( ip ); (* B *)
  477. S.GET( bp + 1, byte ); S.PUT( ip, byte ); INC( ip ); (* G *)
  478. S.GET( bp + 0, byte ); S.PUT( ip, byte ); INC( ip ); (* R *)
  479. INC( bp, 4 );
  480. END;
  481. END;
  482. END PutLineBE;
  483. PROCEDURE GetLineBE( xformat, width: LONGINT; ip, bp: ADDRESS );
  484. VAR i: LONGINT; byte: CHAR;
  485. BEGIN
  486. CASE xformat OF
  487. | index8:
  488. FOR i := 1 TO width DO
  489. S.GET( ip, byte ); S.PUT( bp, byte ); INC( ip ); INC( bp )
  490. END
  491. | color565, color555, color664:
  492. FOR i := 1 TO width DO
  493. S.GET( ip, byte ); S.PUT( bp + 1, byte ); INC( ip );
  494. S.GET( ip, byte ); S.PUT( bp + 0, byte ); INC( ip );
  495. INC( bp, 2 )
  496. END
  497. | color888:
  498. FOR i := 1 TO width DO
  499. INC( ip );
  500. S.GET( ip, byte ); S.PUT( bp + 2, byte ); INC( ip ); (* B *)
  501. S.GET( ip, byte ); S.PUT( bp + 1, byte ); INC( ip ); (* G *)
  502. S.GET( ip, byte ); S.PUT( bp + 0, byte ); INC( ip ); (* R *)
  503. INC( bp, 3 )
  504. END;
  505. ELSE (* color8888 *)
  506. FOR i := 1 TO width DO
  507. S.GET( ip, byte ); S.PUT( bp + 3, byte ); INC( ip ); (* X *)
  508. S.GET( ip, byte ); S.PUT( bp + 2, byte ); INC( ip ); (* B *)
  509. S.GET( ip, byte ); S.PUT( bp + 1, byte ); INC( ip ); (* G *)
  510. S.GET( ip, byte ); S.PUT( bp + 0, byte ); INC( ip ); (* R *)
  511. INC( bp, 4 )
  512. END;
  513. END;
  514. END GetLineBE;
  515. PROCEDURE NewPattern( d: Display;
  516. CONST image: ARRAY OF SET;
  517. width, height: INTEGER ): X11.Pattern;
  518. VAR
  519. pixmap: X11.Pixmap; pat: X11.PatternPtr;
  520. w, h, i, j, b, dest, srcw, destb, srci, desti: LONGINT;
  521. data: ARRAY 256*32 OF CHAR; (* 256*256 bits *)
  522. BEGIN
  523. i := 0;
  524. WHILE i < LEN( data ) DO data[i] := 0X; INC( i ) END;
  525. w := width; h := height;
  526. srcw := (width + 31) DIV 32; (* number of words in source line *)
  527. destb := (w + 7) DIV 8; (* number of bytes in dest line *)
  528. srci := (height - 1)*srcw; desti := 0;
  529. WHILE srci >= 0 DO
  530. i := 0; j := 0; b := 0; dest := 0;
  531. LOOP
  532. dest := dest DIV 2;
  533. IF b IN image[srci + j + 1] THEN INC( dest, 80H ) END;
  534. INC( b );
  535. IF b MOD 8 = 0 THEN
  536. data[desti + i] := CHR( dest ); INC( i ); dest := 0;
  537. IF i >= destb THEN EXIT END
  538. END;
  539. IF b = 32 THEN
  540. b := 0; INC( j );
  541. IF j >= srcw THEN
  542. WHILE i < destb DO data[desti + i] := 0X; INC( i ) END;
  543. EXIT
  544. END
  545. END
  546. END;
  547. INC( desti, destb ); DEC( srci, srcw )
  548. END;
  549. Machine.Acquire( Machine.X11 );
  550. pixmap := X11.CreateBitmapFromData( d.xdisp, d.primary, ADDRESSOF( data[0] ), w, h );
  551. Machine.Release( Machine.X11 );
  552. IF pixmap = 0 THEN HALT( 99 ) END;
  553. pat := S.VAL( X11.PatternPtr, Unix.malloc( SIZEOF( X11.PatternDesc ) ) );
  554. pat.x := 0; pat.y := 0; pat.w := width; pat.h := height; pat.pixmap := pixmap;
  555. RETURN S.VAL( LONGINT, pat )
  556. END NewPattern;
  557. PROCEDURE InitNames;
  558. VAR cwd: ARRAY 128 OF CHAR; i: LONGINT;
  559. BEGIN
  560. UnixFiles.GetWorkingDirectory( cwd );
  561. COPY( Machine.version, winName );
  562. Strings.Append( winName, ", Work: " ); Strings.Append( winName, cwd );
  563. COPY( winName, iconName);
  564. i := 0;
  565. WHILE iconName[i] > ' ' DO INC( i ) END;
  566. iconName[i] := 0X
  567. END InitNames;
  568. PROCEDURE getDisplayName;
  569. VAR adr: ADDRESS; i: INTEGER; ch: CHAR;
  570. BEGIN
  571. Unix.GetArgval( "-display", dispname );
  572. IF dispname = "" THEN
  573. adr := Unix.getenv( ADDRESSOF( "DISPLAY" ) );
  574. IF adr # 0 THEN
  575. i := 0;
  576. REPEAT S.GET( adr, ch ); INC( adr ); dispname[i] := ch; INC( i ) UNTIL ch = 0X;
  577. ELSE dispname := ":0"
  578. END
  579. END
  580. END getDisplayName;
  581. PROCEDURE OpenX11Display( ): X11.DisplayPtr;
  582. VAR xdisp: X11.DisplayPtr; screen, depth: LONGINT;
  583. BEGIN
  584. getDisplayName;
  585. xdisp := Api.OpenDisplay( dispname );
  586. IF xdisp = 0 THEN
  587. Trace.String( "Cannot open X11 display " ); Trace.StringLn( dispname ); Unix.exit( 1 )
  588. END;
  589. screen := X11.DefaultScreen( xdisp );
  590. depth := X11.DefaultDepth( xdisp, screen );
  591. IF depth < 8 THEN
  592. Trace.StringLn( "UnixAos needs a color display. sorry." ); Unix.exit( 1 )
  593. END;
  594. Trace.String( "X11 Display depth = " ); Trace.Int( depth, 1 ); Trace.Ln;
  595. RETURN xdisp
  596. END OpenX11Display;
  597. PROCEDURE CreateColors( d: Display );
  598. VAR col: INTEGER;
  599. visualInfo: X11.VisualInfo;
  600. BEGIN
  601. Machine.Acquire( Machine.X11 );
  602. col := 0;
  603. WHILE col < 256 DO d.pixel[col] := col; INC( col ) END;
  604. IF (d.depth > 8) & (X11.MatchVisualInfo( d.xdisp, d.screen, d.depth, X11.TrueColor, visualInfo ) = 1) THEN
  605. d.visual := visualInfo.visual;
  606. ELSIF X11.MatchVisualInfo( d.xdisp, d.screen, d.depth, X11.PseudoColor, visualInfo ) = 1 THEN
  607. d.visual := visualInfo.visual
  608. END;
  609. d.bigEndian := FALSE;
  610. IF d.depth > 8 THEN
  611. d.bigEndian := d.visual.blueMask > d.visual.redMask
  612. ELSE (* pseudo color *)
  613. d.cmap := X11.CreateColormap( d.xdisp, d.primary, d.visual, X11.AllocAll );
  614. X11.SetWindowColormap( d.xdisp, d.primary, d.cmap );
  615. d.foreground := d.pixel[FG];
  616. d.background := d.pixel[BG];
  617. X11.SetWindowBackground( d.xdisp, d.primary, d.background );
  618. X11.ClearWindow( d.xdisp, d.primary )
  619. END;
  620. Machine.Release( Machine.X11 );
  621. d.planesMask := ASH( 1, d.depth ) - 1
  622. END CreateColors;
  623. PROCEDURE InitPalette( d: Display );
  624. VAR f: Files.File; r: Files.Reader; red, green, blue: CHAR; i, cols: INTEGER;
  625. BEGIN
  626. IF d.depth >= 8 THEN cols := 256 ELSE cols := 16 END;
  627. f := Files.Old( "Default.Pal" );
  628. IF f # NIL THEN
  629. Files.OpenReader( r, f, 0 );
  630. FOR i := 0 TO cols - 1 DO
  631. r.Char( red ); r.Char( green ); r.Char( blue );
  632. d.SetColor( i, ORD( red ), ORD( green ), ORD( blue ) )
  633. END
  634. END;
  635. d.defPal := d.rgb
  636. END InitPalette;
  637. PROCEDURE SuppressX11Cursors( d: Display );
  638. VAR
  639. fg, bg: X11.Color; src, msk: X11.PatternPtr;
  640. image: ARRAY 17 OF SET; i: INTEGER;
  641. noCursor: X11.Cursor;
  642. BEGIN
  643. fg.red := 256*d.rgb[FG].r; fg.green := 256*d.rgb[FG].g; fg.blue := 256*d.rgb[FG].b;
  644. bg.red := 256*d.rgb[BG].r; bg.green := 256*d.rgb[BG].g; bg.blue := 256*d.rgb[BG].b;
  645. FOR i := 1 TO 16 DO image[i] := {} END;
  646. src := S.VAL( X11.PatternPtr, NewPattern( d, image, 16, 16 ) );
  647. msk := S.VAL( X11.PatternPtr, NewPattern( d, image, 16, 16 ) );
  648. Machine.Acquire( Machine.X11 );
  649. noCursor := X11.CreatePixmapCursor( d.xdisp, src.pixmap, msk.pixmap, fg, bg, 1, 1 );
  650. X11.DefineCursor( d.xdisp, d.primary, noCursor );
  651. Machine.Release( Machine.X11 )
  652. END SuppressX11Cursors;
  653. PROCEDURE InitFormat( d: Display );
  654. BEGIN
  655. IF d.depth = 8 THEN
  656. d.format := Displays.index8;
  657. d.xformat := index8
  658. ELSIF d.depth = 15 THEN
  659. d.format := Displays.color565;
  660. d.xformat := color555
  661. ELSIF d.depth = 16 THEN
  662. d.format := Displays.color565;
  663. IF d.visual.blueMask = 0FH THEN d.xformat := color664
  664. ELSE d.xformat := color565
  665. END
  666. ELSIF d.depth = 24 THEN
  667. d.format := Displays.color8888;
  668. d.xformat := color888
  669. ELSIF d.depth = 32 THEN
  670. d.format := Displays.color8888;
  671. d.xformat := color8888
  672. ELSE
  673. d.format := unknown
  674. END;
  675. END InitFormat;
  676. PROCEDURE CreateGC( d: Display );
  677. BEGIN
  678. Machine.Acquire( Machine.X11 );
  679. d.gc := X11.CreateGC( d.xdisp, d.primary, 0, 0 );
  680. IF d.gc = 0 THEN Machine.Release( Machine.X11 ); HALT( 45 ) END;
  681. X11.SetPlaneMask( d.xdisp, d.gc, d.planesMask );
  682. X11.SetGraphicsExposures( d.xdisp, d.gc, X11.True );
  683. X11.SetBackground( d.xdisp, d.gc, d.background );
  684. Machine.Release( Machine.X11 );
  685. END CreateGC;
  686. PROCEDURE InitFunctions( d: Display );
  687. BEGIN
  688. d.xfunc[replace] := X11.GXcopy;
  689. d.xfunc[paint] := X11.GXor; (* not used *)
  690. (* drawing in invert mode with BackgroundCol on BackgroundCol is a no-op: *)
  691. IF S.VAL( SET, d.background )*S.VAL( SET, d.planesMask ) # {} THEN
  692. d.xfunc[invert] := X11.GXequiv
  693. ELSE
  694. d.xfunc[invert] := X11.GXxor
  695. END;
  696. d.currcol := -1; d.currmode := -1;
  697. END InitFunctions;
  698. (* PB - 2010-04-20
  699. Return:
  700. -1: absolute width and height according to DisplaySize config string.
  701. else: value from 50 to 100 as scaling factor, argument variables width and height are unspecified.
  702. Lower limit is either 50% as scaling factor or 640x480 as absolute size.
  703. *)
  704. PROCEDURE GetDisplaySize(VAR width, height: LONGINT): LONGINT; (* % of Screen [50% ... 100%] *)
  705. VAR buf: ARRAY 64 OF CHAR; size, i: LONGINT; c: CHAR; absolute: BOOLEAN;
  706. BEGIN
  707. Machine.GetConfig( "DisplaySize", buf );
  708. IF buf = "" THEN size := 100
  709. ELSE
  710. size := 0; c := buf[0]; i := 0;
  711. WHILE (c >= '0') & (c <= '9') DO
  712. size := 10*size + ORD( c ) - ORD( '0' );
  713. INC( i ); c := buf[i]
  714. END;
  715. IF c = 'x' THEN
  716. width := size;
  717. size := 0;
  718. INC( i ); c := buf[i];
  719. END;
  720. WHILE (c >= '0') & (c <= '9') DO
  721. size := 10*size + ORD( c ) - ORD( '0' );
  722. INC( i ); c := buf[i]
  723. END;
  724. IF (width # 0) & (size # 0) THEN
  725. height := size;
  726. absolute := TRUE;
  727. ELSIF (width # 0) THEN (* failed to read two numbers -> fall back to scaling *)
  728. size := width;
  729. width := 0
  730. END;
  731. IF absolute THEN
  732. size := -1;
  733. IF width < 640 THEN width := 640; END;
  734. IF height < 480 THEN height := 480; END;
  735. ELSE
  736. IF size < 50 THEN size := 50 END;
  737. IF size > 100 THEN size := 100 END
  738. END;
  739. END;
  740. RETURN size
  741. END GetDisplaySize;
  742. PROCEDURE Install*;
  743. VAR disp: Display; res: LONGINT; s, w, h: LONGINT; xdisp: X11.DisplayPtr;
  744. BEGIN
  745. InitNames; xdisp := OpenX11Display( );
  746. s := GetDisplaySize( w, h );
  747. NEW( disp, xdisp, w, h, s, s );
  748. disp.SetName( "XDisplay" );
  749. disp.desc := "X11 display driver";
  750. Displays.registry.Add( disp, res );
  751. END Install;
  752. BEGIN
  753. NEW( imgBuffer, 10000 )
  754. END XDisplay.