view.txt, V1.04, 14.11.1993 T H E V I E W P R O T O C O L ================================================================= 0. Introduction I. The Purpose(s) Of The View Protocol II. Using The View Protocol III. Implementing The View Protocol 1. Who is the viewer? 2. What kinds of files can be displayed? 3. How can I tell the viewer what is to be shown? 4. What does the viewer do? 5. The VIEW_XXX Messages a. View A File b. Further Communication 6. The Messages 0. Introduction =============== The View Protocol was developed by Peter Seitz and Dieter Fiebelkorn to make it possible for a GEM application to display files (using an external viewer) without being forced to implement a viewer for the various file formats itself, and to provide a uniform method of communication between the application and the viewer (so that the application can use any viewer, rather than just one particular viewer). There are already several applications that can be used as viewers. They are GEM-View (Dieter Fiebelkorn), 1st-View/1st-Guide (Guido Vollbending), and ShowImage (Peter Seitz). When installed as accessories, these applications can be instructed (by other applications) to view files. This experimental version of the View Protocol is implemented in GEM- View and ShowImage. IT IS STRONGLY RECCOMMENDED THAT ALL PROGRAMMERS USE AND EXPERIMENT WITH THIS PROTOCOL! We hope that eventually it will become a standard. Suggestions and comments are welcome; please send them to Peter Seitz at one of the following addresses: Peter Seitz, Robert-Koch-Str.6, 63225 Langen, GERMANY E-Mail (Internet): seitz@rbg.informatik.th-darmstadt.de or seitz@isa.informatik.th-darmstadt.de This protocol should be quite easy to implement for both the writers of viewers and the writes of applications. It should provide substantial benefits for the user as well, since he will be able to use his favourite viewer with all applications. --Peter Seitz In the following dicussion, "viewer" refers to the accessory or application that is used to display the file(s) and "application" always refers to the program that requests the services of the viewer. I. The Purpose(s) Of The View Protocol ====================================== The View Protocol was developed to allow an application to: * Determine if a viewer is already in memory (without knowing the name of the viewer). If no viewer is available, the application can start the viewer itself (if the name is available). * Determine what type of files can be displayed by the available viewer. * View files in various formats (using the viewer) and receive feedback from the viewer (using a uniform message protocol). II. Using The View Protocol =========================== It is very easy for the user to use the facilities of the View Protocol. If there is a view-accessory (GEM-View, ShowImage) that supports the View Protocol, and the application supports the View Protocol, nothing needs to be done. If there is no resident view- accessory (or the desired viewer does not support the View Protocol) then the user should install an environment variable called "View" with the full pathname of the desired viewer as its value. The way that this can be done is described in section III.1 (below). III. Implementing The View Protocol =================================== The View Protocol is based on parts of the XAcc-protocol, so a programmer planning to implement the View Protocol should obtain a copy of the XAcc-Protocol (xacc_mt.txt). 1. Who is the viewer? ===================== First, an application should determine if there is a viewer that the user prefers. It does this by (in this order) looking for an environment variable called "View", looking for a cookie in the cookie jar called "View", and then looking for an environment variable called "SHSHOW" (which is used by the MultiTOS desktop, too). In all cases, the case is significant. The value of each one of these variables is the full pathname of the viewer. The programmer can determine if one of the viewers is in memory (as an accessory, usually, but it is possible for the viewer to be an application with a multitasking operating system) using the appl_find() system call. To use the appl_find() system call, the path and the extension have to be removed from the name of the viewer and must be padded with spaces to a length of eight characters. If this is not done, the appl_find() call will fail. It should be noted that appl_find() is case sensitive, so normally the value MUST be all upper case. It would not be wise to convert the name to upper case, however, as case sensitive file systems may be used under MiNT. If the viewer has not yet sent its XAcc-Identification (the ACC_ID message), the application does this now. This may be the case if the main- application does not support the XAcc-Protocol. If no viewer is found, the application should check the extended name (introduced in version two of the XAcc-Protocol) of all applications and accessories that have sent XAcc-Identification messages for the string "2View" (this is the application type "viewer") or the string "NView" (this is the generic type "viewer"). If either of these strings is found, then the application/accessory in question supports the View Protocol and may be used as a viewer. As in the case of the environment variables, the case of "2View" and "NView" is significant. If there is no viewer in memory, but the one of the environment variables (or the cookie) was found, the application can try to load the viewer itself (using the pathname given in the variable). Please note that wildcards may be used in the extension of the viewer (a view-accessory could be named "XXX.ACC" or "XXX.ACX"). If the "View" environment variable was found, the viewer may be started as an accessory as well using Chameleon or MultiTOS. As a consequence of this, the viewer specified in the "View" environment variable must be able to run as both an application or an accessory. If the viewer cannot run as an accessory, it should be specified using the "SHSHOW" environment variable. Normally, the user should use one of the enironment variables ("View" or "SHSHOW"). These should be placed in the desktop environment, as all applications started by the desktop will inherit its environment. This can be done with special programs (ENVIRON.PRG, JCNBOOT.PRG) or, if MiNT is installed, by placing the following line in MINT.CNF: setenv View C:\GEM_VIEW\GEMVIEW.APP and/or setenv SHSHOW C:\GEM_VIEW\GEMSHOW.PRG Using Mag!X the environment can be set by putting a '#_ENV' - line in the MAGX.INF file, like the following: #_ENV View=F:\SHOW_IMG\SHOW_IMG.PRG The cookie should no longer be used. 2. What kinds of files can be displayed? ======================================== The XAcc-Extended Name of the viewer should contain an entry of the form "X.ext" for every supported file format, where "ext" may be one of the following: X.ART - Art-Director X.ASC - ASCII Parargraphs end with carriage return, and lines may end with a linefeed. X.B&W - Imagelab Image X.BLK - GFA Bit-Block There is a three word header: width minus one, height minus one, planes. X.BMP - OS/2 Bitmap, MS-Windows Bitmap X.CFN - Calamus Font X.CRG - Calamus Raster X.CTX - Calamus Text X.CVG - Calamus Vektor X.DOC - 1stWord Document X.DOO - Doodle Mono X.ESM - Enhanced Simplex X.FNT - GDOS Font (and nothing else!) X.GEM - GEM-Metafile X.GIF - GIF Images X.GVW - GEM-View Internal Format Used by GEM-View internally and should not be in this list! (Hi, Dieter!) //X.HEX - Hex-Dump This is obsolete. It is now called "XDump" X.IFF - IFF-File The .IFF format in general! This should be present if any IFF-file-types are supported. X.IFF.ILBM - IFF InterLeavedBitMap X.IFF.type - Other IFF-file types. X.IMC - Signum!2 Image X.IMG - GEM-Image, XIMG X.JPG - JPEG Image X.MAC - MacPaint Image X.NEO - Neochrome Image X.OUT - The GEM 'OUT' file format. SEE: v_alpha_text() X.PAC - STAD Image X.PC[123] - Degas Compressed Image X.PCX - PC Paintbrush X.P[BGP]M - Portable Bitmap X.PIC - Screen Dump (current resolution) X.PI[123] - Degas Uncompressed Image X.RLE - MS-Window Bitmap X.RSC - GEM Resource File X.RTF - Rich Text Format X.SDO - Signum!2 Document X.SDK - Signum!3 Document X.SNP - Becker Snap Shot This has a three word header: width, height, planes. X.SP[CU] - Spectrum 512 Image X.SUN - Sun Raster File X.TGA - Targa Image X.TIF - TIFF Image X.TN[123Y] - Tiny Image X.TXT - ASCII Lines end with a carriage return and a linefeed. It would be nice if a single linefeed (Unix) or a single CR (Macintosh) would also be accepted. X.XBM - X-Bitmap File XDump - hexdump This is not an extension, but means that the viewer is able to show files as hexadecimal dumps. NOTE: [abc] means one of the characters 'a', 'b', or 'c' and not the string '[abc]'. All other entries starting with 'X.' are reserved for future versions! If you would like to add other formats, please contact Peter Seitz. It would be wise if the entries are unique. I recommend the support of X.IMG, X.GEM and X.OUT, as these are the standard formats for GEM-data-exchange! It should be noted that the file formats listed here that an application supports could be a clue as to which file formats the application will accept using the Drag & Drop protocol. 3. How can I tell the viewer what is to be shown? ================================================= Because of the XAcc2-Protocol, the application knows which message-groups are supported and these messages may be used for communication if the application has the data already in memory (and not within a file). Use the VIEW_xxx messages, discussed in III.5 (below) when that data to be viewed is contained in a file. With these messages the application has the extensive control over what is happening. These messages may be used if, and *ONLY* if, the strings '2View' or 'NView' are found in the viewer's extended XAcc-name. This should normally be the case, though. This may be a problem if the viewer has been started by the application. In this case I would suggest to try to send the messages and see what happens. If the viewer does not support them, no reaction is given (as unknown messages should be ignored!). Otherwise, the viewer will send a response. The viewer is *strongly* reccommended to support the VA_START- message! Of course this has to be tested in its protostatus (if possible, see above). There is no explicit support of the Drag & Drop protocol, as it is a MiNT-specific extension, but programs running under MiNT should understand this protocol! All other protocols, of course, may be used to communicate with the viewer (as long as they provide some method to determine whether or not they are supported). PLEASE keep in mind that pointers to strings in AES messages have to point to global-readable memory (if running in an environment with memory protection)! 4. What does the viewer do? =========================== When the viewer is started, it should check the command line for a list of filenames to view. To be consistant with the direction that the Atari is moving, the viewer should support the ARGV argument passing scheme developed by Atari. The viewer should support the XAcc-Protocol, and answer XAcc- Protocol messages. The viewer should use the Alternate + X key combination to send data using the XAcc-Protocol messages. If the viewer receives the VA_START message, it should determine the type of the file and whether or not the type is supported by itself. The viewer does not have to send a reply to this message. If a reply is needed, the application should send the message to the viewer using the VIEW_FILE message. 5. The VIEW_XXX Messages ======================== This is a description of the View Protocol messages. In contrast to to the VA_START and XAcc messages, these messages provide more refined control of what happens to the viewed file. Please remember that these messages may be used if, and *ONLY* if, the strings '2View' or 'NView' are found in the viewer's extended XAcc-name as described above. In general, there are four messages; VIEW_FILE, which may be sent to the viewer, and VIEW_FAILED, VIEW_OPEN and VIEW_CLOSED that are used to inform the application of what has happened to its file. The viewer is expected to answer *EVERY* VIEW_FILE message it recieves. At the very least, it should send a VIEW_FAILED(VIEWERR_ERROR) message (see below). However, if the viewer does not send an answer and the application expects one, the application should recover by using a timeout value (ten seconds should be sufficient). It is possible for the viewer to send other messages (EX: AV_ACCWINDOPEN) before answering the VIEW_FILE message! NOTE: All strings are null terminated (as in the "C" programming language). a) View A File The VIEW_FILE message is used by the application to inform the viewer that a file is to be displayed. msg[0] = VIEW_FILE msg[3/4] = filename // Must be global-readable (due to MiNT's memory // protection)! msg[5/6] = 0 // reserved! msg[7] = 0 // zero = new file, see below! Notes about "filename" (9.10.1993): - If "filename" ends with a slash/backslash or "filename" is a directory, the fileselector should be opened with "filename" as the current path. - If the terminating byte (0) of "filename" is followed by another string starting with an 'X' ($58), this string gives the file type that "filename" should be displayed as (using the strings from III.2 as a guide) if possible. This could be used to show hex-dumps ("XDump"). This message is always answered by the viewer: If the file could not be displayed, respond with the VIEW_FAILED message: retmsg[0] = VIEW_FAILED retmsg[3/4] = msg[3/4] // Filename (same pointer!) retmsg[5] = errcode // See below. retmsg[6] = 0 // Reserved! retmsg[7] = msg[7] // 0 or window identification. "filename" should *ALWAYS* be the pointer recieved in VIEW_FILE, as only this way the sender can recognize which file was meant, in case msg[7] is zero (and - of cause - no new memory has to be alloced). The "errcode" variable may be a GEMDOS error-code (<0) or one of the following: VIEWERR_ERROR - The error is unspecified. VIEWERR_SIZE - The file is too large, or the wrong size. VIEWERR_COLOR - Unsupported resolution or color. VIEWERR_WID - Wrong window identification. VIEWERR_MEM - Not enough memory It is expected that the viewer inform the user about the error (by printing a message or displaying an alert box), since it will know what the problem is much better than the application. If the file has been displayed, but NO further communication is possible, the viewer sends the VIEW_OPEN message: retmsg[0] = VIEW_OPEN retmsg[3/4] = msg[3/4] // Filename (the recieved pointer) retmsg[5] = viewprot_version // Currently 0 retmsg[6] = 0 // Reserved! retmsg[7] = 0 // 0 = no further communication! If the file has been displayed, and further communication is possible, the viewer sends the VIEW_OPEN message: retmsg[0] = VIEW_OPEN retmsg[3/4] = msg[3/4] // Filename (the recieved pointer) retmsg[5] = viewprot_version // Currently 0 retmsg[6] = 0 // Reserved! retmsg[7] = wid // Not zero! The window identification "wid" refers to the AES identification of the window the file is being displayed in. This seems to be a unique number representing the file, which is used in further communication as an identifier. The currently defined "viewprot_version" is 0. b) Further Communication Once a file is displayed (in a window) and the viewer has returned a non-zero window identification in msg[7], both the application and the viewer may send each other messages refering to this file/window. The "msg[7]" variable will ALWAYS contain the (non-zero) window identification as an identifier! As this is supposed to be unique, the "msg[3/4]" variable should NOT be used to identify the file (if the "msg[7]" variable is not zero). If the viewer receives a wrong window identification, it replies by sending a VIEW_FAILED message: retmsg[0] = VIEW_FAILED retmsg[3/4] = msg[3/4] retmsg[5] = VIEWERR_WID retmsg[6] = 0 retmsg[7] = msg[7] // The wrong window identification. The application receiving this message must NOT use this window identification again, since the case may be that the viewer simply did not send VIEW_CLOSED(wid). The application can perform some operations on the file being viewed: * The window should be closed (and the memory used by the file freed): msg[0] = VIEW_FILE msg[3/4] = NULL // Remove File msg[5/6] = 0 msg[7] = wid // This (obviously) cannot be 0. * If the application knows that the file has been changed, or wants another file to be displayed in the same window, it can send the following message: msg[0] = VIEW_FILE msg[3/4] = filename // This may be different. msg[5/6] = 0 msg[7] = wid // The identification of the window. On the other side, the viewer should inform the application of what is happening to its file: * If the window is closed (the user closed it or the viewer received AC_CLOSE or VIEW_FILE(NULL, wid)), then the viewer should send the following message: msg[0] = VIEW_CLOSED msg[3/4] = filename // This may be NULL and should be ignored! msg[5/6] = 0 msg[7] = wid The "filename" should be the one from the VIEW_FILE message, otherwise it may be NULL, as no new global memory should be allocated. * If the window was closed due to an error, the VIEW_FAILED message may be sent instead: msg[0] = VIEW_FAILED msg[3/4] = filename // This may be NULL and should be ignored! msg[5] = errcode // See above. msg[6] = 0 msg[7] = wid If the viewer does not have the ability to store the identification of the application, it may not inform the application when a window was closed without a message from the application. This is very easy to implement, but may lead to unexpected results. Please send your experiences to Peter Seitz (the addresses he can be contacted at are shown above). c) View Data from memory In Version 1.04 of the View Protocol a new message (VIEW_DATA) has been added, which is used to view data, that has already been read into memory. To indicate the support of this new message, the string 'XViewData' must be within the viewer's extended XAcc-name. msg[0] = VIEW_DATA msg[3/4] = data // pointer to data, incl. header (see below) msg[5/6] = length // total length of header + data msg[7] = wid // same as with VIEW_FILE (see above) where "data" points to: LONG type; // eg '.IMG' WORD head_length; // offset to beginning of data, word alligned! CHAR[] name; // 0-terminated name of variable length If the type is 0, the viewer should try to figure it out hisself. Other possible value for "type" are all file-types listed in III.2, but without the 'X' at the beginning (eg 'Dump' means, that beginning at "data + head_length" "length - head_length" bytes should be displayed as hex-dump). Please note that: * "data" has to point to an even adress, * "data" has to point to global readable memory, * "head_length" is even, * the data of the file is found at "data + head_length" and is in the same form, as it would be in a file of type "type". The viewer recieving VIEW_DATA answers the same way as VIEW_FILE, but 'filename' (= msg[3/4]) should be set to the value of 'data'. The application MUST NOT free the memory pointed to by 'data', before recieving the answer from the viewer; in case of a timeout it should ask the user what to do. 6. The Messages =============== At last, the definitions for the messages: #define VIEW_FILE 0x5600 #define VIEW_FAILED 0x5601 #define VIEW_OPEN 0x5602 #define VIEW_CLOSED 0x5603 #define VIEW_DATA 0x5604 #define VIEWERR_ERROR 0 #define VIEWERR_SIZE 1 #define VIEWERR_COLOR 2 #define VIEWERR_WID 3 #define VIEWERR_MEM 4 // 0x56xx = 'V' as in 'View'! All other message values ranging from 0x5600 to 0x56FF are reserved for future extensions of the View Protocol and should be ignored for now.