2 unit IIUWGRAPH: class;
\r
4 { this predefined class enables basic graphic operations
\r
5 for DOS machines based on 486 or 386 processors }
\r
7 { this document gives the specification of new version of IIUWGRAPH
\r
8 class made in October 1994 by Frederic Pataud à Pau
\r
11 { the early versions of library IIUWGRAPH have been elaborated by
\r
12 Piotr Carlsson, Miroslawa Milkowska, Janina Jankowska,
\r
13 Michal Jankowski at Institute of Informatics,
\r
14 University of Warsaw 1987,
\r
15 and added to Loglan system by Danuta Szczepanska 1987,
\r
17 the recent versions were done at LITA, Pau,
\r
19 Pawel Susicki (1991) for Unix,
\r
20 Sebastien Bernard (1992) for ATARI, see a separate document,
\r
21 Eric Becourt et Jerôme Larrieu (1993) for Unix and Xwindows, see a
\r
22 separate document on Xiiuwgraf ,
\r
26 fait à Pau, le 15 Novembre 1994, par Andrzej Salwicki, LITA}
\r
28 { the predefined class IIUWGRAPH is included in all versions of interpreter of
\r
29 Loglan, with the exception of the present version of interpreter for VAX/VMS.}
\r
33 hidden MaxX, MaxY, current_X, current_Y, is_graphic_On,
\r
34 current_Colour, current_Background_Colour, current_Style,
\r
35 current_Palette, current_Pattern ;
\r
42 { the screen's coordinates are
\r
44 (0,0) ----------------------> (MaxX,0)
\r
49 (0, MaxY) (MaxX,MaxY)
\r
54 var currentDriver : integer, { see NOCARD below }
\r
55 current_X, current_Y: integer { it is the current position }
\r
56 is_graphic_On: Boolean, { evidently tells whether we are in
\r
58 current_Colour : integer, { }
\r
59 current_Background_Colour : integer,
\r
60 current_Style : integer, { }
\r
61 current_Palette : integer,
\r
64 unit GRON : procedure (i: integer);
\r
65 { procedure sets the monitor in graphic mode and clears the buffer
\r
66 of screen. The parameter determines the resolution and the number of
\r
68 The user should assure that the resolution chosen should correspond to that
\r
69 which set by means of command
\r
70 SET go32 drivers {path}<driver.file> <width> <height><noColours>
\r
72 set go32 drivers c:\loglan\svga\drivers\vesa.grn gw 1024 gh 480 nc 256
\r
73 An execution of instruction call gron(i) must precede any of the
\r
74 graphic commands described below.
\r
77 unit GROFF : procedure;
\r
78 { the procedure sets the monitor in the text mode filling it with
\r
80 DO NOT FORGET to set the monitor in the text mode before
\r
81 you terminate your program
\r
84 unit NOCARD : function : integer;
\r
85 { the value given by this function determines the type of the currently used
\r
86 monitor and it is equal to
\r
87 1 for Hercules mono card,
\r
89 3 for IBM CGA mono 320 x 200
\r
90 4 for IBM CGA mono 640 x 200
\r
93 7 for Unix versions equipped with XWindows
\r
94 You can not call the function nocard before GRON sets the graphic mode
\r
97 unit CLS : procedure;
\r
98 { the screen will be cleared and filled with colour 0 }
\r
101 unit VIDEO : procedure( A: array of integer);
\r
102 { this procedure can not be applied with egaint = EGA/VGA card }
\r
103 { the worktime buffer will be associated with the array A.
\r
104 A call of VIDEO does not change the contents of the buffer.
\r
105 All subsequent calls of the procedures modifying the screen will
\r
106 concern the array A. The screen does not change.
\r
107 A ready image can be moved to the screen with the help of
\r
108 GETMAP/PUTMAP procedures or it can be stored on disk.
\r
109 The array should have 16 kBytes for IBM CGA card or
\r
110 32 kBytes for Hercules card.}
\r
112 { PROCEDURES CONTROLLING THE COLOURS }
\r
114 unit COLOR : procedure(co : integer);
\r
115 { sets current color to co
\r
116 for monochrome displays, 0 means black, non-0 - white
\r
117 for color displays, 0 means background
\r
121 unit STYLE : procedure(styl : integer);
\r
122 { sets style of lines and fill shades to a combination
\r
123 of current color and background color (for mono -
\r
124 white and black, respectively) according to 5 predefined
\r
134 where '*' means current color, '.' background colour
\r
135 When drawing the segments the subsequent pixels will have colour determined
\r
136 by cyclic application of style pattern. The first and the last pixels of a segment
\r
137 will have always current colour.
\r
138 When filling contours the given style will be applied to horizontal lines with even
\r
139 coordinate. The style for odd lines is determined automatically.
\r
140 The same applies for perpendicular lines.
\r
144 unit BORDER : procedure (background_Colour: integer);
\r
146 { sets actual background color to i ( i = 0,1,...,15 ) }
\r
149 unit PALLET : procedure (nr : integer);
\r
152 the codes of colors are as follows
\r
174 { PROCEDURES CONTROLLING POSITION }
\r
176 unit MOVE : procedure (x,y :integer);
\r
177 { procedure MOVE sets the current position on the screen on the pixel
\r
181 { precondition of MOVE:
\r
182 0*x*MaxX & 0*y*MaxY
\r
185 unit INXPOS : function: integer;
\r
186 { function INXPOS returns the x coordinate of the current position }
\r
189 unit INYPOS : function : integer;
\r
190 { function INYPOS returns the y coordinate of the current position }
\r
193 unit PUSHXY : procedure;
\r
194 { pushes current position, color & style onto the stack.
\r
195 The stack is kept internally, max depth is 16
\r
199 unit POPXY: procedure;
\r
201 { restores position, color & style from internal stack }
\r
204 unit DIAGONAL : procedure;
\r
205 var ix, iy : integer;
\r
210 call DRAW(ix+10, iy+10);
\r
217 { PROCEDURES SERVING POINTS & LINES}
\r
219 unit POINT : procedure(x,y: integer);
\r
220 { moves current position to pixel (x,y) and sets it to the current color
\r
223 unit INPIX : function (x,y : integer) : integer;
\r
225 moves to pixel (x,y) and returns its color setting;
\r
229 unit DRAW : procedure( x,y : integer);
\r
231 draws a line from current screen position to (x,y);
\r
232 sets current position to (x,y);
\r
233 line is drawn in current color, with both terminal pixels
\r
234 always turned white ( non-background) for non-black
\r
235 ( non-background ) line color.
\r
236 Bresenham's algorithm is used, pixels belonging to the segment
\r
237 change their state depending on current colour and style.
\r
240 unit intens: procedure(Size :integer; xCoord,yCoord:arrayof integer,
\r
241 Colour,Filled :integer);
\r
242 /* draw a polygon*/
\r
243 { draw a simple, closed polygon of Size points, the edges of the polygon go from
\r
244 (xCoord[i], yCoord[i]) to (xCoord[i+1], yCoord[i+1]) for i = 1, ..., Size-1
\r
245 The colour used will be Colour. The polygon will be filled iff Filled<>0.
\r
248 unit CIRB : procedure (xi, yi, rx,ry : integer, alfa, beta : real,
\r
249 cbord, fill : integer);
\r
252 draws a circle (or ellipse, depending on aspect value, see below),
\r
253 optionally filling its interior;
\r
254 does not preserve position;
\r
255 (xi,yi) - are center coordinates,
\r
256 rx - radius in pixels (horizontally),
\r
257 ry - radius in pixels (perpendicularly),
\r
258 alfa, beta - starting & ending angles; if alfa=beta a full
\r
259 circle is drawn; values should be given in radians;
\r
260 cbord - border color,
\r
261 fill - if fill <>0, interior is filled in current style&color
\r
264 unit hfill: procedure( x : integer);
\r
265 { draw an horizontal line between the current position and
\r
266 (x,currentY) with the current color, after it change the current
\r
267 position to (x, currentY)
\r
270 unit vfill: procedure( y : integer);
\r
271 { draw a vertical line between the current position and
\r
272 (currentX,y) with the current color, after it change the current
\r
273 position to (currentX,y)
\r
276 unit patern: procedure( x1,y1,x2,y2,c,b : integer);
\r
277 { draw a rectangle between the points (x1,y1) and (x2,y2) with the
\r
278 color c (the current color is not change). if b=0 then the box is
\r
279 empty else it is filled.
\r
282 { Procedures operating on bitmaps }
\r
284 unit GETMAP : function (x,y : integer) : arrayof integer;
\r
285 {saves rectangular area between current position as
\r
286 top left corner and (ix,iy) as bottom right corner,
\r
287 including border lines;
\r
288 position remains unchanged.
\r
289 array of integer should have
\r
290 4+(rows**columns/8* *coeff)
\r
291 bytes. The coefficient coeff is 1 for Hercules, 2 for CGA, 4 for EGA
\r
293 ATTENTION: in DOS 286 environment a bigger size of the array may
\r
294 necessitate the use of loglan with the option H+, see also memavail
\r
297 unit PUTMAP : procedure ( a: arrayof integer);
\r
298 {sets rectangular area of screen pixels to that saved
\r
299 by "getmap" in "iarray";
\r
300 same size is restored, with top left corner in current
\r
302 position remains unchanged.
\r
305 unit ORMAP : procedure ( a : arrayof integer);
\r
306 {same as putmap, but saved bitmap is or'ed into screen
\r
307 rather than just set.
\r
310 unit XORMAP : procedure ( a: arrayof integer);
\r
311 {same as putmap, but saved bitmap is xor'ed into screen
\r
312 rather than just set.
\r
316 {Procedures operating on characters and strings}
\r
318 unit outstring: procedure(x,y: integer, s: string, back_col, front_col: integer);
\r
319 { x, y are the coordinates where to put the string,
\r
320 s is the string to be shown, in front_col colour letters on the back_col
\r
324 unit track: procedure( x,y,c,valeur : integer);
\r
326 { write an integer value valeur at the position (x,y) with the color c.
\r
327 It does not change the current position nor the current color
\r
330 unit inkey : function : integer;
\r
332 { returns next character from keyboard buffer;
\r
333 0 is returned if buffer is empty;
\r
334 special keys are returned as negative numbers;
\r
335 ALT-NUM method may be used for entering character codes
\r
336 above 127 (this makes entering special keys 128-132
\r
338 if a character is returned, it is also removed
\r
339 from the buffer, so MS-DOS will not see it (CTRL-C!);
\r
340 typeahead is allowed, echo is suppressed.
\r
343 unit HASCII : procedure(c: integer);
\r
344 {'xor's the character = chr(c) in a 8*8 box with top left corner
\r
345 in the current position;
\r
346 moves current position by (8,0);
\r
347 call hascii(0)- sets complete box to black ( =background ),
\r
348 with no change in position.
\r
349 BIOS ROM font for IBM color card is used. If the font
\r
350 table is not at F000:FA6E, the character will probably
\r
351 be unrecognizable, and most certainly wrong.
\r
352 For codes >127, table pointed to by interrupt vector 31
\r
357 unit hfont: function( x,y,lg,min,max,default,col_f,col_e,col_c : integer):
\r
360 { arrange a small 1 line window for reading an integer value from this
\r
362 the position of the window corner is (x, y),
\r
363 the length of the window is lg characters,
\r
364 the value v should be greater than min and smaller than max,
\r
365 the default value read is default,
\r
366 the colour of the window is col_f,
\r
367 the colour of the digits is col_e,
\r
368 the colour of cursor is col_c
\r
370 reads in graphic mode an integer in the window which begins at the (x,y)
\r
371 position, window is lg caracteres long. the maximum length of the
\r
372 integer that is read is 10. there is a default value, a minimum value
\r
373 and a maximum value. the window is drawn with the col_f color, the
\r
374 cursor is in the col_c color and the integer is writing in the col_e
\r
375 color. you can use 0..9,+,-,backspace,escape and return keys. }
\r
378 unit HPAGE : procedure(x,y,long: integer, A: arrayof char, back, front: integer);
\r
379 { this procedure arranges a 1-line high window in position x,y of length
\r
380 long in which a portion of text A is shown in colour front on the
\r
381 background colour back.
\r
382 Making use of keys controlling the cursor {left, right, PgUp, PgDn}
\r
383 the user can scroll the text (horizontally) in the window. Pressing the
\r
384 Enter key terminates the procedure}
\r
393 { init -lors de l'initialisation de la souris, on peut définir les événements qui vont faire réagir la fonction
\r
394 getpress; le premier et le deuxième paramètre représentent respectivement la souris et le clavier, si une valeur non
\r
395 nulle est donnée comme paramètre alors getpress réagira à l'événement.
\r
397 Une paire (1,1) va permettre de prendre en compte à la fois les événements de la souris et ceux du clavier;
\r
398 une paire (1,0) quand à elle ne prendra en compte que la souris. Pour une plus grande souplesse d'utilisation, il est
\r
399 possible lors du programme, après l'initalisation, de changer cette prise en compte, cela se fera par l'appel de la
\r
400 procedure getmovement, procédure ayant les mêmes paramètres (avec le même ordre) que la fonction init.
\r
402 Pour detecter les événements, on utilisa la fonction getpress, qui retourne un booléen indiquant la présence
\r
403 ou l'absence d'événement (respectivement les valeurs true et false). Il est bon de noter qu'ainsi définie la fonction
\r
404 getpress n'est pas bloquante. Les paramètres en retour sont soit nuls (pas d'événement) soit correspondent:
\r
406 bool:=getpress(v,p,h,l,r,c : integer);
\r
407 v = position en y de la souris
\r
408 p = keyboard status (Touche control_left,control_right, alt, alt_gr, shift_left, shift_right)
\r
409 h = position en x de la souris
\r
412 c = boutons de la souris (0=aucun, 1=gauche, 2=droite, 3=gauche et droite)
\r
413 Nb: le bouton central n'est pas géré.
\r
415 NOTEZ BIEN! Lorsque les événements du clavier sont pris en compte dans le gestionnaire, il ne faut pas utiliser
\r
416 les fonctions d'entrées clavier readl, readln, hfont, hfont8, hpage, inkey,...) sous peine de plantage de
\r
420 unit init: procedure(checkMouse, checkKeyboard: integer);
\r
421 { initializes the Mouse driver.
\r
422 tells which events will be checked:
\r
423 if checkMouse <>0 then the events of Mouse will be reported to getpress, see below otherwise ignored;
\r
424 if checkKeyboard <>0 then the events of Keyboard will be reported to getpress, otherwise ignored
\r
425 Attention please! While the events of the keyboard are taken under control by init or getmovement
\r
426 do not use the functions or procedures: read, readln, hfont, hfont8, hpage, inkey that read keys
\r
427 YOU RISK TO HANG YOUR SYSTEM!
\r
431 unit getmovement: procedure(checkMouse, checkKeyboard: integer);
\r
432 tells which events will be checked:
\r
433 if checkMouse <>0 then the events of Mouse will be reported to getpress, see below otherwise ignored;
\r
434 if checkKeyboard <>0 then the events of Keyboard will be reported to getpress, otherwise ignored
\r
435 Attention please! While the events of the keyboard are taken under control by init or getmovement
\r
436 do not use the functions or procedures: read, readln, hfont, hfont8, hpage, inkey that read keys
\r
437 YOU RISK TO HANG YOUR SYSTEM!
\r
440 unit getpress: function(v,p,h,l,r,c : integer): Boolean;
\r
441 { v = y coordinate of the cursor,
\r
442 h = x coordinate of the cursor,
\r
443 p = keybord status control_left,control_right, alt, alt_gr, shift_left, shift_right
\r
444 l = code of key pressed
\r
446 c = buttons pressed (0=aucun, 1=gauche, 2=droite, 3=gauche et droite)
\r
447 Nb: the middle button is not taken into account.
\r
451 unit showcursor: procedure;
\r
452 {the cursor becomes visible and follows the movements of the mouse}
\r
455 unit hidecursor: procedure;
\r
456 {the cursor becomes invisible}
\r
463 Enclosed you find a sample program
\r
465 Program SystemeGraph;
\r
466 (* by Frederic Pataud, October 1994 *)
\r
468 Pref iiuwgraph block (* inherit the graphic functions *)
\r
470 Pref mouse block (* inherit the mouse functions *)
\r
473 (*****************************************************************************)
\r
474 (* P r o g r a m m e P r i n c i p a l *)
\r
475 (*****************************************************************************)
\r
476 var v,p,h,i : integer,
\r
478 rep : arrayof char,
\r
480 xx,yy : arrayof integer,
\r
481 status,code,x,y,flags,button : integer;
\r
485 call gron(0); (* enter the graphic mode *)
\r
486 call init(1,0); (* initialize the mouse, disregard the keyboard events, check for mouse events *)
\r
488 call showcursor; (* show cursor *)
\r
489 call patern(5,5,635,475,2,0); (* make a frame around the screen *)
\r
490 call outstring(10,10,"x=",2,0);
\r
491 call outstring(100,10,"y=",2,0);
\r
492 call outstring(10,30,"status = ",2,0);
\r
493 call outstring(10,50,"code = ",2,0);
\r
494 call outstring(10,70,"flags = ",2,0);
\r
495 call outstring(10,90,"button = ",2,0);
\r
496 call patern(100,210,300,320,3,1); (* make a rectangle filled in colour 3 *)
\r
498 array xx dim (1:6);
\r
499 array yy dim (1:6);
\r
500 xx(1):=410; yy(1):=10;
\r
501 xx(2):=450; yy(2):=30;
\r
502 xx(3):=460; yy(3):=50;
\r
503 xx(4):=430; yy(4):=80;
\r
504 xx(5):=420; yy(5):=40;
\r
505 xx(6):=480; yy(6):=30;
\r
506 call intens(6,xx,yy,8,1); (* show a polygon filled*)
\r
511 call intens(6,xx,yy,15,0); (* show another polygon empty *)
\r
513 call cirb(500,300,50,40,100,3500,10,0); (* draw an empty pie or camembert *)
\r
514 call cirb(400,400,40,40,600,4000,11,1); (* draw a filled pie *)
\r
517 i:=hfont(100,350,6,-9999999,9999999,500,9,0,15); (* read integer from a window *)
\r
518 call hpage(100,400,10,unpack("Il fait beau dans ma verte campagne"),9,0); (* show text *)
\r
519 rep:=hfont8(100,430,10,80,unpack("tototutu"),9,0,15); (* read text *)
\r
521 call getmovement(1,1); (* take into consideration both key events and mouse events *)
\r
524 d:=getpress(v,p,h,l,r,c); (* ask about an event *)
\r
526 then call outstring(10,400,"Event",2,0);
\r
527 call patern(80,25,130,100,0,1);
\r
528 call track(40,10,v,0,4); (* print integer *)
\r
529 call track(140,10,p,0,4);
\r
530 call track(80,30,h,0,4);
\r
531 call track(80,50,l,0,4);
\r
532 call track(80,70,r,0,4);
\r
533 call track(80,90,c,0,4);
\r
534 if((h=164 and l=27) or (c=3)) (* exit if either two buttons were pressed c=3 or Ctrl+Esc key *)
\r
539 call groff; (* leave the graphic mode and return to the text mode *)
\r
541 for i:=lower(rep) to upper(rep)
\r