GUI : Xmodula test program

Xmodula comes with a small and simple test program called 'XTest'. With Mocka 0608m it compiled immediately. This program is relatively small so it is quite easy to comprehend and understand. Below is the source code.

MODULE XTest;

 (*
  * This example module shows how to access X11 from a Modula-2 program.
  * To make the code easy to read, no check are performed; the program is
  * therefore likely to crash if something goes wrong.
  * A real program should always check returned values for possible errors.
  *
  * This program assumes an X display with at least 16 colors.
  *)

FROM  SYSTEM 	   IMPORT  ADDRESS, ADR;
FROM  Xglobal 	   IMPORT  CARD8, INT, CARD, CARD32, SET32;
FROM  X  	   IMPORT  Window, WindowPtr, KeySym, Expose, KeyPress, ButtonPress,
      		   	   ExposureMask, ButtonPressMask, KeyPressMask, None, Colormap, AllocAll, 
  			   DoRed, DoGreen, DoBlue;
FROM  Xlib         IMPORT  Display, DisplayPtr, Screen, ScreenPtr, GC, XOpenDisplay,
      		   	   XCreateSimpleWindow, XSelectInput, XCreateGC, XSetBackground,
			   XSetForeground, XClearWindow, XMapRaised, XFreeGC, XDestroyWindow,
			   XCloseDisplay, XEvent, XNextEvent, XFillRectangle, XFillArc,
			   XDrawString, XColor, XCreateColormap, XStoreColors, XSetWindowColormap,
			   XFreeColormap, XDrawString16, XChar2b; 
FROM  Xutil        IMPORT  XSetStandardProperties, XLookupString;
FROM  XMacros 	   IMPORT  DefaultScreen, BlackPixel, WhitePixel, DefaultRootWindow, RootWindow,
      		   	   DefaultVisual; 

VAR    dis		   : DisplayPtr;  	(* Connection to the X server *)
       screen		   : INT; 		(* Default screen number *)
       win		   : Window; 		(* My window *)
       gc		   : GC; 		(* Graphics context *)
       cmap 		   : Colormap; 		(* My private Colormap *)
       black, white	   : CARD32; 		(* Pixel numbers for black and white colors *)
       res    		   : INT; 		(* dummy variable to fetch X calls' results *)


PROCEDURE InitX;	   (* Create everythings that is necessary to draw on a window *)

CONST  WindowName   = "My window";
       IconName     = "HI!";

VAR    windowName, iconName 	: ARRAY[0..59] OF CHAR;

BEGIN
  windowName := WindowName; 	(* Mocka does not allow ADR(Const) *)
  iconName := IconName;     	(* therefore copy it in a variable. *)


  dis := XOpenDisplay (NIL);	   	(* Connect to the X server *)
  screen := DefaultScreen (dis);
  black := BlackPixel (dis, screen);
  white := WhitePixel (dis, screen);
  cmap := 0; 	      	    	    	(* No colormap created yet *)

 (* Create a window *)
  win := XCreateSimpleWindow (dis, DefaultRootWindow(dis), 0, 0, 200, 300, 5, white, black);
  res := XSetStandardProperties (dis, win, ADR(windowName), ADR(iconName), None, NIL, 0, NIL);
  res := XSelectInput (dis, win, ExposureMask + ButtonPressMask + KeyPressMask);

 (* Create a graphic context *)
  gc  := XCreateGC (dis, win, SET32 {}, NIL);
  res := XSetBackground (dis, gc, white);
  res := XSetForeground (dis, gc, black);

 (* Bring the window to the front *)
  res := XMapRaised (dis, win)
END InitX;


PROCEDURE CreateColormap;	(* Create a grayscale colormap and attach it to the window *)

VAR	  i	   : INT;
   	  tmp	   : ARRAY[0..15] OF XColor;

BEGIN
  FOR i:= 0 TO 15 DO	(* Create a grayscale *)
    WITH tmp [i] DO
      pixel := i;  	(* By default, Xglobal.CARD8 = CHAR; therefore, use CHR() *)
      flags := CHR (DoRed + DoGreen + DoBlue);
      red := i * 4369; 	   	     	     	(* 15x4369 = 65535 = 2^16 - 1  :-) *)
      green := i * 4369;
      blue := i * 4369
    END
  END;

 (* Create the Colormap *)
  cmap := XCreateColormap (dis, RootWindow(dis, screen), DefaultVisual(dis, screen), AllocAll);
  res := XStoreColors (dis, cmap, ADR(tmp), 16);

  res := XSetWindowColormap (dis, win, cmap);		 (* Attach it to the window *)
  black := 0;		    	       			 (* Update black and white *)
  white := 15
END CreateColormap;


PROCEDURE CloseX;

BEGIN
  res := XFreeGC (dis, gc);
  res := XDestroyWindow (dis, win);
  IF cmap <> 0 THEN  res := XFreeColormap (dis, cmap)  END;
  res := XCloseDisplay (dis)
END CloseX;


PROCEDURE Redraw;		(* Redraw our window's content *)

VAR      i, j	     : INT;

BEGIN
  res := XSetForeground (dis, gc, white);
  res := XFillRectangle (dis, win, gc, 0, 0, 200, 300);
  FOR i := 0 TO 15 DO
    res := XSetForeground (dis, gc, i);
    j := i * 6;
    res := XFillArc (dis, win, gc, j, j + 100, 200 - j * 2, 200 - j * 2, 0, 360 * 64)
  END;
  res := XSetForeground (dis, gc, black);
  res := XDrawString (dis, win, gc, 10, 10, "Press 'q' to quit")
END Redraw;


PROCEDURE ClearTextArea;

BEGIN
  res := XSetForeground (dis, gc, white);
  res := XFillRectangle (dis, win, gc, 10, 12, 190, 32);
  res := XSetForeground (dis, gc, black)
END ClearTextArea;


VAR
  event		: XEvent;
  key		: KeySym;
  text		: ARRAY [0..255] OF CHAR;
  ch		: ARRAY [0..15] OF XChar2b;
  length	: CARDINAL;

BEGIN
  InitX;
  (* You can remove the next line to use the standard colors *)
  (* CreateColormap; *)

  LOOP
    res := XNextEvent(dis, event);
    IF  (event.type = Expose) THEN  Redraw  END;
    IF  (event.type = KeyPress) AND
       (XLookupString(ADR(event.xkey), text, key, NIL) = 1) THEN
      IF (text[0] = "q") THEN EXIT END;
      ClearTextArea;

      (* Convert CHAR to XChar2b so we can use a custom string length *)
      length := 0;
      WHILE (text [length] <> 0C) AND (length < 16) DO
        ch [length].byte2 := text[length]; 
	ch [length].byte1 := 0C;
    	INC (length)
      END;

      res := XDrawString (dis, win, gc, 10, 26, "You pressed the key:");
      res := XDrawString16 (dis, win, gc, 10, 42, ADR(ch[0]), length)
    END;
    IF  (event.type = ButtonPress)  THEN
      ClearTextArea;
      res := XDrawString (dis, win, gc, 10, 26, "Button pressed")
    END
  END;

  CloseX;

END XTest.
   
The program was made by Nicky and is part of the XModula package (download it via the download section).

Page created 31 August 2008,

Page equipped with FroogleBuster technology