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 [...] 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