aboutsummaryrefslogtreecommitdiff
path: root/vendor/x11iraf/xgterm/NOTES
blob: f14fa19dd7fa93ba04789033023a17f31776977f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
xgterm.NOTES -- Some random design notes made while writing this code.  Not
intended to be useful to anyone reading this code.


To do:
	Object manager
	    add bitmap support
	    add event handling support
	Gterm widget
	    add cell array
	    pixrect operations?
	    minor odds and ends
	Gtermio
	    modify to use object manager
	    add messaging capability
	GIO
	    add messaging capability
	    modify cell array support as needed


Pixmaps
	cache by name
	new entry replaces old
	entries are never freed unless overwritten
	for lookup, check cache first then look for file (normal resource
	    translation)

	typical bitmap:

	#define opendot_width 16
	#define opendot_height 16
	#define opendot_x_hot 7
	#define opendot_y_hot 7
	static char opendot_bits[] = {
	   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,
	   0x60,0x03,0x20,0x02,0x60,0x03,0xc0,0x01,0x00,0x00,0x00,0x00,
	   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

	types of bitmaps - bitmap, pixmap, cursor

	createBitmap name width height data
	createPixmap name width height depth fg_color bg_color data
	createCursor name source mask fg_color bg_color x_hot y_hot


Event handling

	addEventHandler <procname> <event-mask> [<event-mask>...]
	userEventHandler {widget event-type time wx wy rx ry other}
	    where "other" is a event-specific list of fields

Event structs

	event masks, event names are numerous
	most events have these fields:
	    type, time, x_win, y_win, x_root, y_root other
	other fields:
	    key:		state (key or button mask), keycode
	    button:		state (key or button mask), button code
	    motion:		state (key or button mask), is_hint
	    crossing:		mode (normal, grab, ungrab)
	    focus:		mode (normal, grab, ungrab)
	    visibility:		state
	    error:		error_code, request_code, minor_code

	    keycode|button|mode|state

Event masks

	Button1MotionMask
	Button2MotionMask
	Button3MotionMask
	Button4MotionMask
	Button5MotionMask
	ButtonMotionMask
	ButtonPressMask
	ButtonReleaseMask
	ColormapChangeMask
	EnterWindowMask
	ExposureMask
	FocusChangeMask
	KeyPressMask
	KeyReleaseMask
	KeymapStateMask
	LeaveWindowMask
	NoEventMask
	OwnerGrabButtonMask
	PointerMotionHintMask
	PointerMotionMask
	PropertyChangeMask
	ResizeRedirectMask
	StructureNotifyMask
	SubstructureNotifyMask
	SubstructureRedirectMask
	VisibilityChangeMask

Event names

	ButtonPress
	ButtonRelease
	CirculateNotify
	CirculateRequest
	ClientMessage
	ColormapNotify
	ConfigureNotify
	ConfigureRequest
	CreateNotify
	DestroyNotify
	EnterNotify
	Expose
	FocusIn
	FocusOut
	GraphicsExpose
	GravityNotify
	KeyPress
	KeyRelease
	KeymapNotify
	LeaveNotify
	MapNotify
	MapRequest
	MappingNotify
	MotionNotify
	NoExpose
	PropertyNotify
	ReparentNotify
	ResizeRequest
	SelectionClear
	SelectionNotify
	SelectionRequest
	UnmapNotify
	VisibilityNotify


GTERM CELL ARRAY

	Colormap
	    use pseudocolor visual if possible
	    a fixed number of well defined sharable, read-only cells
	    a variable number of private read-write cells
	    the private cells are allocated at runtime when the
		application allocates a colormap
	    the graphcap entry specifies the maximum number of private
		colormap cells that can be allocated
	    a private colormap is used if the requested cells cannot
		be allocated
	    there is only one colormap per gterm widget (if there are
		multiple cell arrays they share the same colormap)

	Cell arrays (obsolete term?)
	    A cell array is mapping of an MxN array of 8 bit pixel values
		to a region of the screen.
	    The pixel values in a cell array range from 0 to NC, and are
		contiguous in that range.  NC is the number of colors in
		the gterm colormap.  The first few values starting at 0
		are statically allocated and cell array pixels will
		normally start at the first dynamically allocated value.
	    The cell array mapping defines the transformation used to paint
		a region of the Gterm window from the cell array pixels.
		Scaling and axis flipping are possible.
	    Cell arrays are defined and written to in separate steps.  A
		given write operation may modify only part of the MxN pixels
		of the cell array.

	New operations
	    write colormap	Writes N cells of the gterm colormap starting
				at a given pixel value.

	    define cell array	Define transformation for cell array N.
				Several cell arrays may be active.

	    write cell array	Write to a subregion of a cell array (operates
				in cell array pixels, not screen pixels).

	    Arbitrary regions of the colormap or a cell array may be
	    modified, allowing for very interactive operations.

	    Binary pixel values must be encoded for transmission between the
	    client and server.  The simplest encoding adds 040 to the value
	    of each pixel (byte), resulting in a printable byte stream.
	    Control codes may be used for compression schemes.

	Alternative scheme
	    Store cell array in off screen buffer.  This is the same as
		above except that in the above scheme the pixels are not
		saved.
	    Modifying any pixel data, or editing the mapping causes the
		affected region of the screen to be rewritten.
	    The advantage of this approach is that operations such as zoom
		and pan can be implemented merely by modifying the mapping.
		Given multiple cell arrays, one can also do blink, split
		screen, etc.
	    Perhaps mappings should be separate from cell arrays.  The
		same array may be mapped to more than one region of the
		screen, or a mapping may map portions of more than one
		array.
	    Fundamental items are pixel array, mapping, colormap

	Pixmap operations
	    Create host or display pixmap
	    Destroy pixmap (or all such pixmaps)
	    Copy data to/from pixmap and screen
	    Read a file into a pixmap or series of pixmaps
	    Append pixmap to a file

	    Should be combined with Obm capabilities for creating and
	    referencing pixmaps.

	    Pixmap operations can be used for a number of purposes,
	    including movie making.

Imaging Procedures

	Images (rasters) are implemented internally in Gterm using either
	ximages or off screen pixmaps.  Which format is used is decided at
	raster create time and is controlled by a Gterm resource.  This is
	transparent to the client application.  Currently only 8 bit rasters
	are supported.

	       GtRasterInit (gt)
	     GtAssignRaster (gt, raster, drawable)
	     GtCreateRaster (gt, raster, type, width, height)
	    GtDestroyRaster (gt, raster)
     exists = GtQueryRaster (gt, raster, &width, &height)
	     n = GtNRasters (gt)

	      GtWritePixels (gt, raster, pixels, x1, y1, nx, ny)
	       GtReadPixels (gt, raster, pixels, x1, y1, nx, ny)
    pixmap = GtCreatePixmap (gt, src, x, y, width, height)
	       GtCopyPixmap (gt, pixmap, dst, x, y, width, height)

	    GtWriteColormap (gt, first, nelem, r, g, b)
	     GtReadColormap (gt, first, nelem, r, g, b)

	     GtInitMappings (gt)
	       GtCopyRaster (gt, rop, src,sx,sy,snx,sny, dst,dx,dy,dnx,dny)
	       GtSetMapping (gt, mapping, src,sx,sy,snx,sny, dst,dx,dy,dnx,dny)
	       GtGetMapping (gt, mapping, src,sx,sy,snx,sny, dst,dx,dy,dnx,dny)
	    GtEnableMapping (gt, mapping, enable)
	   GtRefreshMapping (gt, mapping)

	For the widget class we can also have commands to operate upon
	pixmaps created by or written into a gterm widget.

	        createPixmap name src [x y width height]
	 	  copyPixmap name dst [x y width height]
	       destroyPixmap name

	There should also be commands to delete pixmaps, write pixmaps to
	files, and read pixmaps from files.

	The imaging routines operate in window or pixmap pixels.  If a
	window is resized, any mappings referencing the window are modified
	to reflect the change in size.  A query-size function is required
	to pass the window size in pixels back to the client.  A set-size
	(resize window) procedure is also desirable to allow the client to
	attempt to set the window to the optimum size for an image.

	The client uses a special library of procedures for imaging.  These
	use GIO escapes to communicate with the stdgraph kernel.  The
	stdgraph kernel uses special ESC codes to communicate with the
	server.

	Applications which do only simple imaging will use GIO calls to
	put a cell array and assign colors, using NDC coordinates for the
	cell array mapping.  More demanding applications that must operate
	in pixel space, operate directly on image buffers, etc., will use
	the GIO escapes directly.  The stdgraph kernel will keep track of
	the window size and perform NDC to pixel space conversions for the
	put cell array call.


Implementation

	Code structure

	    client
		gio
		gim
		    gki_escape
						  | (--IPC--)
			stdgraph kernel
			    serial encoding
						  | (--IPC--)
				gtermio
				obm
				    gterm widget


	Simple graphics applications use the high level GIO routines for
	imaging.  These include put/get cell array and put/get colors, with
	gset being used to select colors for drawing.

	A small library of routines are used in client programs that have
	more demanding imaging requirements.  These are implemented using
	GIO escapes and operate in pixel space, providing direct access to
	the gterm imaging functions.

	The GIO escapes are processed by the stdgraph kernel.  This uses ASCII
	escape sequences defined in graphcap to communicate with the server.
	The GIO escape codes are defined in lib$gescape.h.

	The gtermio code in Xgterm processes these escape sequences and
	converts them into calls to the imaging routines in the gterm widget.

	The object manager also provides routines for calling the gterm
	imaging routines from within UI code.

	The actual Xlib based imaging code is in the gterm widget.


Complications

	Cursor mode - wants to buffer all GKI instructions, including the
	GIM escapes, some of which are voluminous.  If any interactive image
	editing, redrawing, etc. is done without initializing things, this
	could be a lot of data.  Would like cursor mode to work in the sense
	that one can redraw the screen, zoom and pan.

	Cursor readback - for a cursor read within a mapped region of the
	screen, the logical thing is to return raster coordinates rather
	than Tek window coordinates.  The server should make the mapping
	transparent, so that the client gets raster coordinates regardless
	of the image offset, scale, any axis flip, and so on.

	Cursor mode strategy - all GIM escapes issued by the client are
	executed, but only setmapping instructions are buffered.  During a
	cursor mode redraw the setmapping instructions are edited to reflect
	the cursor mode zoom/pan (this should be done by a GIM routine), and
	retransimitted to the server at the time that they are encountered
	in the display list.  In most cases this will result in the image
	data being redrawn at the appropriate time, e.g. after a frame draw
	and area clear, and before any overlaid graphics is drawn.

	This requires that the server not initialize the imaging system on
	every frame clear (probably the imaging subsystem should be
	initialized when the cursor mode frame buffer is cleared, rather
	than when the server screen is cleared).  The space required to
	buffer setmapping instructions is mimimal.  A disadvantage is that
	:.write/read will not save or redisplay image data.  The major
	advantage is that this provides full cursor mode zoom/pan capability
	and is time and space efficient.

	To encapsulate manipulation of the GIM escapes in the cursor mode
	code, a GIM (stdgraph kernel) routine should be called when a GIM
	escape is executed to edit the instruction, if any, left behind in
	the cursor mode buffer.  This routine will have access to the
	cursor mode frame buffer and will edit it as necessary, e.g.
	deleting the instruction, replacing it, or editing earlier GIM
	escapes in the same frame buffer.

	Cursor readback strategy - to solve this problem it appears to be
	necessary to have the server pass back the "cursor number" in a
	cursor read.  When a cursor read occurs there is no way the client
	can predict which cursor will be read; the server selects the cursor
	depending upon the pointer location.  The cursor number is the Tek
	cursor, a raster cursor, or a region of a window.  The WCS number
	in the cursor value struct passed back to the client indicates
	which cursor was read.


Timings

	Time to copy 631296 byte text file through a tty/pty

	    lepus	8-9sec	 70 Kb/sec
	    tucana	2sec	300 Kb/sec


Cursor Handling

	The general scheme is that when the cursor is read, the server
	determines which raster the cursor is in and returns pixel
	coordinates relative to this raster, regardless of how the raster is
	mapped to the screen.  The return cursor value includes the raster
	number, pixel X and Y coordinates, and the keystroke (keycode) which
	terminated the cursor read.

	Since the Tek cursor value struct does not provide adequate
	resolution or any provision for the raster number, a custom cursor
	return value is required.  gtermio will continue to support a Tek
	cursor, using a special escape to initiate a custom cursor read.

	gki_retcursor needs to be modified to provide more coordinate
	resolution and to allow the "cursor" (raster) number to be returned.

	In cursor mode, WCS selection will use the CN/raster number instead
	of screen position to determine the WCS to be used.  A WCS maps a
	range of world coordinates (e.g. image pixel coordinates) to a
	viewport in NDC space.


Current cursor mechanism

	ESC SUB - initiate standard Tek cursor read
	user types key to terminate graphics input mode

	server returns cursor value encoded as
	    key
	    hix;  lox
	    hiy;  loy
	    trailer1;  trailer2
	x, y are encoded in Tek screen coordinates, 0-1023,0-779

	gki_getcursor (fd, x, y, key, cursor)
	    stg_getcursor (cursor number)
		call stg_readcursor to read cursor
		returns GKI cursor value struct
		    cursor number, x, y, key

	stg_readcursor (cursor, x, y, key)
	    stg_rdcursor (tty, cursor, x, y, key, output_rc)
		set raw mode
		getc until pattern is matched
		clear raw mode
		stg_encode to decode cursor value
		return x, y, key

	rcursor (fd, curval, maxch)
	    grc_cursor (rc, stream, x, y, key, ppos)		(screen)
		gtr_readcursor (stream, x, y, key)		(screen)
		    gki_getcursor (fd, mx, my, key, 0)		(GKI)
	    grc_scrtowcs (stream, x, y, xc, yc, wcs)		(WCS)
		grc_scrtondc (sx, sy, mx, my)			(NDC)
		wcs = grc_selectwcs (tr, mx, my)
		grc_settran (w, ct)
		grc_ndctowcs (ct, mx, my, wx, wy)		(WCS)
	    format and return cursor value as a string		(WCS)

	screen coordinates - workstation screen/window
	NDC coordinates - normalized screen coordinates (no zoom)
	WCS coordinates - world coordinates in active WCS

	WCS - max 16 per screen
	    wx1,wx2,wy1,wy2	range of world coordinates
	    sx1,sx2,sy1,sy2	viewport, NDC coordinates
	    xtran, ytran	type of transformation in each axis
	    clip		flag to clip at viewport boundary

	WSTRAN - cursor mode ndc-to-screen
	    vx1,vx2,vy1,vy2	range of NDC coordinates
	    mx1,mx1,my1,my2	range of GKI coordinates


Cursor mechanism with rasters

	The key concept underlying this scheme is that GKI (NDC) coordinates
	refer to the "raster" the cursor is in, rather than to the screen,
	hence are independent of the raster-to-screen mapping.  One
	logically draws into a raster, and any mappings defined on the
	raster take care of rendering the graphics on the screen.  A cursor
	read returns both screen coordinates, used for cursor mode zoom/pan,
	and image raster GKI/NDC coordinates.  A special case is raster 0,
	the screen (actually the drawing window), which is what GKI/NDC
	coordinates always referred to in the past.  When drawing into
	raster 0 one is drawing directly to the screen.  When drawing into a
	raster, one is still drawing to the screen, but via any mapping or
	mappings defined on the raster.

	Each raster has zero or more WCS associated with it.  The WCS
	associated with the raster defines a mapping between some world
	coordinate system, e.g., image pixel coordinates, and NDC or
	normalized raster coordinates.  To get from world coordinates to
	pixels on the screen, one converts from world coordinates to NDC
	coordinates via the WCS, then from NDC coordinates to raster pixels,
	then from raster pixels to screen pixels via the mapping.  To be
	more precise, the full transformation is as follows:
	    
	    GIO in the client:
		world -> NDC
		NDC -> GKI (clipped at viewport)

	    Cursor mode in the CL:
		GKI to "screen" (zoomed/clipped-GKI) coordinates
		zoomed-GKI to Tek coordinates for serial protocol

	    Gtermio code in the server:
		Tek coordinates to raster pixel coordinates for current
		    drawing raster

	    Gterm widget code:
		raster pixel coordinates to screen pixel coordinates
		    via a mapping defined on the raster
		repeat for each mapping defined on the raster

	Graphics drawing for raster overlays requires that the server treat
	the input Tek encoded coordinates (1024x780) as normalized for the
	current raster.  If the raster number is zero the normal drawing
	operation (into the display window) takes place.  If the raster
	number is nonzero any mappings defined on the referenced raster
	define where the graphics is drawn on the screen.  If a mapping is
	disabled no drawing takes place.  Graphics are automatically clipped
	at the boundary of the destination rect defined by a mapping.

	In a cursor read operation, the server determines which raster if
	any is mapped to the region of the screen the cursor is in.  Both
	screen (raster 0) and raster coordinates are returned using a
	special cursor value struct.  The cursor value return by RCURSOR
	(hence =gcur and clgcur) returns the world coordinates defined by
	the selected WCS for the current raster.  If no WCS is defined NDC
	coordinates are returned.  If multiple WCS are defined for a raster
	cursor mode selects the "nearest" viewport as it has always done
	for screen coordinates.

	About the only alternative to the above scheme is to have the server
	return raster pixel coordinates.  The problem with this is that this
	is inconsistent with the GIO graphics model, and the WCS cannot be
	used to return world coordinates, or to draw graphics overlays.

	A complication with this scheme is that normally WCS 1 is used for
	the screen (raster 0).  Sometimes more than one WCS is used.  Hence
	to make a strict association between WCS number and raster number
	would require that raster numbers be allocated accordingly in the
	client.  Also it is not clear what happens if there is more than one
	WCS defined for a raster.  To get around this problem a way is
	needed to define which raster a WCS refers to.  This can be done
	without a (significant) protocol change by encoding the frame number
	in the existing, little used WCS_CLIP field of the existing WCS
	structure.


Colormap Sharing

	A gterm resource selects type of colormap: default, private, shared
	    default means default screen colormap, shared by all apps
	    private means colormap is used only by this gterm instance
	    shared means non-default colormap shared by multiple gterms

	In the case of the default colormap, read-only or read-write cells
	are allocated out of the screen default colormap.  This guarantees
	that the colors of non-gterm windows will not be affected when gterm
	colors are allocated, but it may not be possible to allocate all
	requested colors, or having allocated these colors to a gterm 
	widget it may not be possible to run other applications.  Use of
	the default colormap is appropriate for applications that do not
	use many colors.

	A private colormap is allocated and used by only a single gterm.
	This guarantees that the expected number of colors will be available,
	and prevents one gterm from changing another's colors.  The main
	disadvantage is that the window will go black (or whatever) when
	the pointer is not in the window.

	A shared colormap is a non-default (custom) colormap shared by
	multiple gterms.  Allocation of colors is guaranteed, but when one
	gterm modifies the colormap all gterms using the shared colormap
	are affected.  They are however still visible and if they contain
	similar data the display may still appear reasonable.  There can
	be multiple shared colormaps, each with a different name.

	It is possible to use a trick to minimize colormap flashing when
	private or shared colormaps are used.  This works so long as the
	default colormap has only a limited number of colors allocated,
	and the gterm client needs only a limited number of colors (e.g.
	200 or so out of 256).  The trick is to allocate as many colors as
	possible from the default colormap, assigning the same pixels for
	colors in the custom colormap.  The default colormap is then copied
	to the private (or shared) colormap, and the new colors are stored
	in both colormaps.  The newly allocated colors are then freed in
	the default colormap.  The custom colormap will then inherit most
	of the color assignments of the default colormap, and in turn the
	default colormap may still have the initial color assignments from
	the custom colormap.

	Differences will appear as both colormaps change thereafter, but in
	practice many color assignments are fairly static so colormap
	flashing should be minimized.  The default colormap can be updated
	periodically by repeating the allocate, store, copy, and free
	sequence, e.g., when the custom colormap is modified.

	Custom gterm colormap allocation strategy: in the normal case reserve
	216 colors for private use.  The remaining cells are copied from the
	default colormap to minimize colormap flashing.  If the gterm client
	requests more than 216 colors the full colormap is allocated.

		  0 -  37	copied from default colormap
		 38 - 253	reserved for gterm client
		254 - 255	copied from default colormap

	The point where the gterm colormap starts (e.g. 38) should be defined
	by a resource as there is no guarantee which end of the default
	colormap static colors will be allocated at.

	if (use default colormap) {
	    allocate read-write cells
	    store colors
	} else {
	    if (don't have colormap yet) {
		map colormap name to atom
		if (named gterm colormap not found) {
		    # Create gterm colormap.
		    open connection to display
		    create colormap, allocate all colors
		    call XSetRGBColormaps to set colormap property
		    call XSetCloseDownMode to make colormap permanent
		    close display
		} else {
		    call XGetRGBColormaps to get colormap property
		    get colormap id
		}
		set colormap id for gterm window
		call XSetWMColormapWindows to notify WM of custom colormap
	    }
	    store new colors in custom colormap
	    if (match colormaps) {
		copy global cells from default colormap
		attempt to allocate cells in default colormap
		attempt to store new colors in default colormap
		free cells allocated above
	    }
	}

	If the gterm widget has a private colormap different than that of
	its top level window, XSetWMColormapWindows must be called for gterm
	window focus in/out events to indicate to the WM that the colormap
	for the gterm window is to be loaded.


Windowing the Display

	Given a range of display pixel values and a normalized colormap,
	apply a threshold/gain transformation to window the display (i.e.,
	write new screen colormap).  This needs to be done in the UI to
	provide acceptable interactive response.

	    GtWindowDisplay (gw, offset, slope)

		offset		(0.5 +/- X) center of windowed region 
		slope		(+/- X) slope of transfer function

	    The transfer function is applied to the normalized colormap
	    and the output colormap is written to the screen.

	To window over a greater dynamic range one must regenerate the
	display pixel values from the raster or image (this can be done by
	the client).  For example, the client application can display a
	histogram and the user can mark the region to be written to the the
	gterm raster pixels.

	The marker facilities described in the next section can be used to
	implement real-time display of the grayscale transfer function if
	desired.  The message facility could also be used to transfer the
	image histogram and information about the histogram region loaded
	into a raster, for use with the transfer function to generate a
	full display of the grayscale mapping from disk image to screen.


Graphics Markers

	A "marker" is a graphics object, defined on a raster, which can be
	created or destroyed, which can draw itself, or which can modify
	(move or resize) itself in response to pointer events.  Markers have
	attributes such as the marker type (text, line, circle, polygon,
	etc.), color, line width, center, width, height, visibility, and
	sensitivity.  Markers can accept callbacks which are executed when
	the object is interactively moved or resized.

	Markers can be used to annotate a window, as if one were drawing
	into a window.  The chief difference between a marker and a simple
	drawing operation (such as a polyline) is that markers are not just
	lines on the screen, but actual objects capable of responding to
	requests or taking independent action.

	Generic functions

	    create
	    destroy
	    copy
	    set attribute
	    get attribute
	    raise, lower

	Generic attributes

	    type
	    visibility
	    autoRedraw
	    sensitivity
	    foreground, background		text markers
	    linecolor, linewidth
	    knotcolor, knotsize
	    fillcolor, fillstyle		polygon markers
	    width, height
	    x, y

	Marker types

	    text		font, string
	    line		vertices
	    box
	    rectangle
	    circle
	    ellipse
	    polyline		vertices
	    polygon		vertices

	Procedures

		  gm = GmGreate (gt, type, interactive)
		    gm = GmCopy (gm)
		      GmDestroy (gm)
	          GmAddCallback (gm, func, client_data)
		  gm = GmSelect (gt, x, y, &what)

		      GmMarkpos (gm)
		       GmRedraw (gm, func, erase)
		        GmRaise (gm, ref_gm|NULL)
		        GmLower (gm, ref_gm|NULL)
		       GmNotify (gm, events)

		          GmAdd (gm, x, y)
		       GmDelete (gm, x, y)
			 GmMove (gm, x, y)
		       GmResize (gm, x, y)
		       GmRotate (gm, x, y)

	         GmSetAttribute (gm, attribute, value, type)
	         GmGetAttribute (gm, attribute, value, type)
	          GmSetVertices (gm, points, first, npts)
	   npts = GmGetVertices (gm, points, first, maxpts)

	raster = GtSelectRaster (gt, st, sx, sy, rt, &rx, &ry, &mp)
		    GtMapVector (gt, mp, dir, st, sv, dt, dv, npts, clip)

	Markers operate in screen coordinates (raster 0).  The SelectRaster
	and MapVector routines may be used to convert to and from raster
	coordinates if desired.

	Actions
		     create   (type)
		    destroy   marker
			set   (attr, value)
		      raise   marker
		      lower   marker
		     notify   callback

		    markpos   marker
		 markposAdd   marker point		button1-down
		     redraw   marker			button1-up
			add   point
		     delete   point
	      deleteDestroy   point or marker		delete or backspace
		       move   marker
		     resize   marker
		 moveResize   point or marker		button1-motion
		     rotate   marker			shift-button1

	Marker specific functions (internal)

		 bool =  select (gm, x, y, &what)
		      classinit (gm)
			markpos (gm, &rect)
			 redraw (gm, function)

			    add (gm, x, y)
			 delete (gm, x, y)
			   move (gm, x, y)
		         resize (gm, x, y)
			 rotate (gm, x, y)

	The marker specific functions are the methods for each marker
	class.  The functions add, delete, move etc. merely edit the marker
	descriptor.  A separate call to redraw is required to redraw the
	modified marker.

	Actions such as deleteDestroy and moveResize will select one of the
	listed actions based upon the pointer coordinates.  For example with
	moveResize, if the pointer is in the center of a marker the entire
	marker is moved, and if the pointer is near a point the point is
	moved or the marker resized depending upon the type of marker.

	The default translations for these actions are shown at the right.
	These translations are in effect only when the pointer is over a
	marker that is sensitive and visible.  The cursor will change to
	indicate that the marker is active; the cursor type will indicate
	whether the entire marker, a single point, or add-point will be
	selected if button1 is pressed at that location.  In addition, the
	default translation for button1-down for the window is create
	rectangle.  Hence a rectangle object can be created and dragged out
	with the left button at any time just using the default
	translations.  This can be used prior to executing a command to
	indicate the region to be operated upon.

	Actions such as move, resize, rotate, etc. do not redraw the object
	(unless autoRedraw is set).  Instead, these actions do a GXor redraw
	of the marker at the old location, edit the marker according to its
	type, and then do another GXor redraw at the new location.  When
	tracking the cursor this produces a rubber-band effect.  When
	tracking completes (e.g., button1-up) the screen is refreshed at the
	markpos position, erasing the old marker, any affected markers are
	redrawn at the markpos position, and the edited marker is redrawn at
	the new location.

	A Marker is created with GmCreate.  If the interactive flag is set
	a mode is entered where the mouse is used to set the initial
	position and size of the object.  The cursor changes to indicate
	that the widget is waiting for input.  The user moves the mouse to
	the position on the screen where the object will go, clicks the left
	pointer, and then does a drag to set the initial size and
	orientation of the object.  When the button is released the create
	object operation is complete, unless the marker type is polygon in
	which case multiple click-and-drag operations are required to
	interactively define the polygon.

	If the create is not interactive, the GmCreate returns immediately,
	and SetAttribute calls are used to set the object attributes and
	then display the object.

	Once a marker has been created the sensitivity attribute controls
	whether the object can be interactively moved or resized with the
	mouse.  If the marker is sensitive, when the pointer is placed
	within the marker or near a vertex or edge the cursor will change to
	indicate that the marker, vertex, or edge can be dragged to move or
	resize the marker.  Alternatively, the delete or backspace key can
	be used to destroy the marker.  This will not actually destroy the
	marker, but will notify the client (via a callback) that the user
	has requested that the marker be destroyed.

	When the mouse is near a sensitive marker a special translation
	table defines the key or pointer bindings associated with the drag,
	delete, etc. marker actions.  Typical bindings would be left pointer
	for create and drag, middle pointer to terminate a sequence such as
	when drawing a polygon or to abort a create object, shift left
	pointer to add a point to an existing polygon, and delete or
	backspace to delete an object, or in add-point mode, the last vertex
	in a polygon.

	All the gterm widget need do is, when there is one or more sensitive
	marker in a window, track the cursor and load the marker translation
	table when the pointer is over a marker which is sensitive.  The
	rest will be done by the marker actions.

	Markers can be used in UI code to provide a more general method of
	position input than a cursor read, which can only specify a single
	point.  For example to input a rectangular region, one would do the
	following:

	    UI selects marker type rectangle
	    UI creates a rectangle marker in interactive mode
		cursor changes to indicate create-object mode
		user positions mouse and clicks left button
		holding button down, user drags out the rectangle
		button up terminates GmCreate
	    UI calls GetVertices and passes polygon back to client
	    UI destroys marker

	    If desired, the client application can draw the polygon again
	    using normal graphics drawing commands (i.e., not as a marker).

	To mark a region on a raster in UI code:

	    UI creates rectangle object in noninteractive mode
		visibility and autoredraw are initially false
	    UI calls SetAttribute to set rectangle position, size, etc.
	    UI sets visibility attribute to cause marker to be drawn

	If the region is to be active, e.g. something should happen if the
	user moves or resizes the region, then the sensitivity should be
	set to true and a callback can be posted to take some action if the
	region is changed.  For example, this could be used to graphically
	pan the image or adjust the colormap.

	Markers are only drawn to the screen, never to the screen pixmap.
	Hence they can be erased by copying from the screen pixmap.  If the
	screen needs to be refreshed the markers are redrawn from the object
	list maintained internally by the gterm widget.


Display of Pixel Dependent Information

	A common feature of image display UIs is the ability to display
	information about the pixel under the cursor, either in sample mode
	or continuously as the cursor is moved.  For maximum flexibility
	one must rely upon the client application to return information about
	a pixel, since usually only the client has full access to the data,
	and the significance of a pixel can be highly application specific.
	An example of this is the display of the cursor position and pixel
	intensity in user coordinates.

	To implement this feature we need the following capabilities.

	    o	The UI posts a callback procedure which is called whenever
		the cursor moves, i.e., which receives pointer-moved events.

	    o	The UI obtains information about the pixel under the pointer 
		from the client.

	    o	The UI displays this information in a text object, either
		overlaid on the image or in a separate text display area.

	The WS already provides the ability to post a callback to receive
	pointer-moved events.  What we need is an efficient way to obtain
	information about the pixel under the cursor.  Due to the overhead
	of the client-server architecture, it is undesirable to query the
	client every time we need information about a pixel.  Hence, we must
	get information for a block of pixels in single query and cache this
	information in the server, sending another query only when the
	pointer moves to a different region of the screen.

	This can be done by sending a request to the client to send a block
	of information (text) for all the points in a grid in pixel space.
	The client responds by generating the text as a message to a UI
	parameter.  The UI then needs a way to select text from the UI
	parameter, and generate another query if the desired data is not
	cached.  

	The cached text consists of a sequence of lines of the form

		raster-x raster-y client-text

	The server will need to cache several such blocks of data, each with
	a header identifying the raster number and the region of the raster
	covered by the cached data.  The object code in the server will
	provide convenience routines for managing and searching this data.


Text Display Facilities

	Real-time display of pixel information requires some way of
	displaying the text passed back by the client via the method
	described in the last section.  Text display can be done either
	using a text widget ouside the gterm window, or using a text marker
	if the text is to be overlaid on the image.  An advantage of using a
	marker for the text overlay is that since the marker is active, the
	user can use the mouse to reposition the text on the screen.


Translations

	The Widget specifies the default translations.  The Widget
	translations resource specifies replacement, augment, or override
	translations.  Additional augment or override translations may
	be specified in a function call (e.g. to cause the widget to invoke
	an application specified menu via a translation).

	On a marker focusout, the widget must restore the gterm window
	translations.

	At initialize time:

	    if (translations resource defined) {
		if (augment or override translations) {
		    defTranslations = compiled Gterm translations
		    compile auxiliary translations
		    set augment or override flag
		} else
		    defTranslations = compiled translations resource
	    } else
		defTranslations = compiled translations resource

	At focusout time:

	    SetValues defTranslations
	    for (each auxiliary translation table)
		augment or override widget translations

	Additional auxiliary widget translations can be specified with
	GtAugmentTranslations or GtOverrideTranslations.

oo