> Spec.Messages New Calls --------- Wimp_SendMessage Wimp_Poll: reason codes 17,18,19 Wimp_TransferBlock SWI Wimp_SendMessage -------------------- Entry: R0 = reason code to be returned to receiving task R1 --> block containing message R2 = task handle of task to receive message or R2 = window handle (message is sent to owner of window/icon) R3 = icon handle (required if R2 = iconbar window handle (-2)) or R2 = 0 (message is broadcast to all tasks in turn) Exit: R2 = task handle of receiver (unless R2=0 on entry) the message is queued the block is updated if R0 was 17 or 18 on entry The messages are queued on a First-In-First-Out basis, and are delivered when Wimp_Poll is next called. Note that a message will only be delivered if the receiving task is still active, and has not masked out the relevant reason code (R0 on entry to Wimp_Poll = mask). Messages sent to a window/icon rather than a task are also tagged so that if the window or icon is deleted then the message is not delivered. Note that pending messages take priority over any other kind of action which might return a reason code from Wimp_Poll. Wimp_Poll reason codes ---------------------- Code Meaning Block size (bytes) 0 Null 0 1 Redraw_Window 4 2 Open_Window 32 3 Close_Window 4 4 Pointer_Leaving_Window 4 5 Pointer_Entering_Window 4 6 Mouse_Click 24 7 User_DragBox 16 8 Key_Pressed 28 9 Menu_Selection variable 10 Scroll_Window 40 11 Lose_Caret 24 12 Gain_Caret 24 13..16 Reserved 17 User_Message variable 18 User_Message_Recorded variable 19 User_Message_Acknowledge variable Wimp_SendMessage with R0 = 17,18,19 (User_Message) -------------------------------------------------- In addition to sending 'ordinary' reason codes to other tasks, such as Open_Window_Request or Mouse_Click, Wimp_SendMessage can be used to send message blocks, using the new reason codes 17,18 and 19. The format of the block on entry to Wimp_SendMessage in these cases is as follows: Entry: +0 size of block ( 20<=size<=256, size MOD 4 = 0) +4 not used +8 not used +12 your_ref (0 if not replying to a previous message) +16 message action (unique) +20.. message data (format depends on message action) Exit: +4 task handle of sender (ie. this task) +8 my_ref (reference number of message (unique non-zero word)) The two fields on exit are filled in by Wimp_SendMessage, and will also be included in the block received at the other end. The three different reason codes (17,18,19) have the following meanings when given to Wimp_SendMessage: 17 User_Message The message is sent by the Wimp to the relevant task. If the message is not delivered (eg. if the task is dead, or it just ignores it), then nothing happens. 18 User_Message_Recorded The message is sent by the Wimp to the relevant task. If the message is not acknowledged by the receiving task, then the Wimp will return the message to the original sender, with the reason code changed to 19. To acknowledge a message, the receiving task must send another message with its 'your_ref' field set to the 'my_ref' field of the original message, before it calls Wimp_Poll again. 19 User_Message_Acknowledge The message identified by the your_ref field is acknowledged. In order to acknowledge a message (ie. to prevent it from being returned to the sender), the receiving task can either send another message or send a User_Message_Acknowledge, which will acknowledge the message without actually sending one in reply. In either case, the my_ref field of the original message should be copied into the your_ref field of the new message, in order to acknowledge it. If the original message was a broadcast, acknowledging it will prevent it from being passed to any further tasks. Note that sending a message type 19 with your_ref=0 and R2/R3 = window/icon handle is one way to discover the handle of the task owning a window/icon (on exit from Wimp_SendMessage R2=task handle) without actually sending a message. Wimp_Poll reason codes 17,18,19 ------------------------------- Note that when receiving messages, a task should not distinguish between message types 17 and 18 in terms of their function - it is the 'message action' field which uniquely determines the purpose of a message. Wimp_Poll reason code 19 means that a type 18 message you sent has been returned to you, since it was not acknowledged (see above). Message Actions --------------- It is envisaged that, in addition to the 'system' message actions (see below), various families of applications may wish to send messages to each other. To ensure that message actions do not clash, it has been decided that the message numbers will be allocated in parallel with SWI chunk numbers. Thus, if you have already been allocated a SWI chunk, you can use message actions in that range for private purposes. If you have not been allocated any SWI chunks, and you need one, you should apply to Acorn to get it! The following message actions have been defined so far: 0 Message_Quit 1 Message_DataSave 2 Message_DataSaveAck 3 Message_DataLoad 4 Message_DataLoadAck 5 Message_DataOpen 6 Message_RAMFetch 7 Message_RAMTransmit 8 Message_PreQuit 9 Message_PaletteChange &400 Message_FilerOpenDir &401 Message_FilerCloseDir &40040 Message_Notify &400C0 Message_MenuWarning &400C1 Message_ModeChange &400C2 Message_TaskInitialise &400C3 Message_TaskCloseDown &400C4 Message_SlotSize &400C5 Message_SetSlot &400C6 Message_TaskNameRq &400C7 Message_TaskNameIs 0 Quit (broadcast) R0 = 17/18 R1!0 = size of data R1!12= 0 ; your ref. R1!16= 0 ; action On receipt of this message, a running Wimp task should tidy up and close down, by calling Wimp_CloseDown and OS_Exit. At this stage, the task should not refuse to close down - if the task has any unsaved data, it should object when it receives the PreQuit message (8), which is always issued prior to the Quit message (see below). 1..7 Data transfer protocol These messages are detailed in a separate section below. 8 PreQuit (broadcast) R0 = 17/18 R1!0 = size of data R1!12= 0 ; your ref. R1!16= 8 ; action On receipt of this message, a running Wimp task should check to see if any data would be lost if it were to close down (ie. if any files have been modified but not saved). If not, the message should be ignored, and the sender of the PreQuit message will follow it up with a Quit message, causing the task to close down. If the task has unsaved data, it should acknowledge the PreQuit message (SWI Wimp_SendMessage with R0=19, R1->original block, R1!8 copied into R1!12), and bring up a suitable dialogue box so that the user can specify whether to save or discard the files. If the user subsequently decides to discard the files, the application should restart the closedown sequence by sending a CTRL-SHIFT-f12 keypress event to the sender of the PreQuit message, as follows: SYS "Wimp_GetCaretPosition",,R1 :REM fill up first 5 words R1!24 = &1FC :REM CTRL-SHIFT-f12 SYS "Wimp_SendMessage",17,R1,prequittask% (prequittask% is the task handle of the sender of the PreQuit message, which can be read from the original message block). The Task Manager module provides a global 'Exit' option, which it executes on receipt of a CTRL-SHIFT-f12 as follows: 1. SWI Wimp_SendMessage, 17,prequitblk,0 2. prequitref = prequitblk!8 ; remember myref field 3. On receipt of Wimp_Poll (19), if message!8 = prequitref then: SWI Wimp_SendMessage, 18,quitblk,0 quitref = quitblk!8 ; remember myref field 3. On receipt of Wimp_Poll (17/18), if message action = Quit then if message block!8 <> quitref then 4. On receipt of Wimp_Poll (19), if message action = Quit then if message block!8 = quitref then The Task Manager issues the PreQuit broadcast first - if this is not acknowledged by any task, it proceeds to issue the Quit broadcast. This means that if any task objects to being closed down, it does so before any of the other tasks is closed down. It also means that if any task contains unsaved data, the task will not be closed down, and the user must re-select the quit option after responding to the task's save/discard confirmation sequence. After sending the Quit broadcast, the Task Manager does not quit itself until it receives its own message back to confirm that all other tasks have been closed down successfully. However, if it receives the message from another task, it should close down immediately. Note that the Task Manager responds to CTRL-SHIFT-f12 being pressed by using a 'grabkeys' window (bit 12 of window flags set) to respond to the user pressing the key. Note that due to the above protocol, any form of closedown sequence (such as one that is required in order to boot a new operating system) must respond to the CTRL-SHIFT-f12 keypress message, even if it is never passed user keystrokes (indeed, it should not respond to the actual user keystrokes, since the Task Manager is supposed to deal with that). 9 Message_PaletteChange (broadcast) R0 = 17/18 R1!0 = size of data R1!12= 0 ; your ref. R1!16= 9 ; action This message should not be acknowledged by any task. The palette utility issues this broadcast whenever the user finishes dragging any of the RGB bars in the palette window, or loads a new palette file. On receipt of the PaletteChange message, a task which needs to alter any internal tables or colour mappings when a palette change occurs should do so, and call Wimp_ForceRedraw if necessary to ensure that the relevant changes are reflected on the screen. Note that since the palette utility will automatically invalidate the whole screen if any of the Wimp's colours change their logical mapping, most tasks do not need to take any notice of this message. See Wimp.Colours for further details of the Wimp colour mappings. This message is not issued when the mode changes, so Message_ModeChange (&400C1) should also be trapped by tasks needing to act on colour mappings. NetFiler messages ----------------- The netfiler uses messages in the NetFS module SWI range (&40040-&4007F). &40040 Message_Notify (broadcast) R0 = 17/18 R1!0 = size of data R1!12= 0 R1!16= &40040 R1?20= station number } of sending station R1?21= network number } R1?22..R1?26 = 5-byte real time when message was received R1?27.. = message (0-terminated) The NetFiler offers this broadcast around to make it easy for another application to pick up the message and display it in some nice way for the user. If the message is not acknowledged, the NetFiler will simply call Wimp_ReportError with the message in the error box, and the string 'Message from station xxx.xxx' in the title bar. Wimp messages ------------- The Wimp-specific messages are allocated in the range &400C0-&400FF (in its SWI range). &400C0 Message_MenuWarning R0 = 17/18 R1!0 = size of data R1!12= 0 R1!16= &400C0 R1!20= address of submenu data R1!24= x-coordinate of top-left of menu R1!28= y-coordinate of top-left of menu R1!32= list of menu selection numbers, terminated by -1 This message will only be delivered by the Wimp if bit 3 of the menu flags of a menu item is set, and the submenu pointer is not null. If this is true, and the user moves the mouse pointer over the right-arrow icon of the menu entry, then instead of directly opening the relevant submenu, the Wimp will generate this message. After processing the information contained in the message block (and possibly amending the submenu data) the application should respond by calling Wimp_CreateSubMenu with the parameters in the message block at offsets 20,24 and 28 (ie. the menu data pointer and x,y coordinates). Note that the submenu could be a dialogue window handle. The list of menu selection numbers indicates the current state of the menu tree, and is the same as that returned by Wimp_Poll (Menu_Select). This information, together with the application's record of which menu tree it last created, is sufficient to determine whereabouts in the menu tree the Wimp currently is. &400C1 Message_ModeChange (broadcast) R0 = 17/18 R1!0 = size of data (20) R1!12= 0 R1!16= &400C1 On receiving this message, a task which needs to make adjustments on a mode change shuld do so. Note that the mode number is not supplied in the message - tasks should NOT use the mode number to determine the vdu variables, but should instead call OS_ReadVduVariables. After sending the Message_ModeChange, the Wimp sends an Open_Window_Request for each window that was open at the time the Wimp_SetMode occurred. This is designed so that if the screen width is reduced (eg. if going from mode 16 to mode 12), the windows will be 'scrunched' into the visible portion of the screen. The mode change also causes the entire screen area to be marked invalid, so all windows will be redrawn. There is a problem, however: if a task wishes to modify a window after the mode change in a way which requires it to be deleted and re-created, the window handle will change. Unfortunately problems will result if this is done on receipt of the Message_ModeChange, since the Wimp will subsequently return an Open_Window_Request for the OLD window handle, not the new one. The solution is that if you need to change the window handle in this way, you should not do it until you receive the Open_Window_Request for the relevant window - in other words, on the Message_ModeChange you should mark the window 'dirty' (in some internal data structure), and on Open_Window_Request check the 'dirty' flag and do the deletion/recreation stuff if required. &400C2 Message_TaskInitialise (broadcast) R0 = 17/18 R1!0 = size of block (including header) R1!4 = task handle of new task R1!12= 0 R1!16= &400C2 R1!20= CAO pointer of task R1!24= amount of application memory used by task R1+28..= Issued by the Wimp when a task calls Wimp_Initialise. This message is picked up by the Task Manager module, and enables it to maintain a list of running tasks. Note that the Task Manager will only notice tasks which start up after it, so it should be the first desktop module in the module list. &400C3 Message_TaskCloseDown (broadcast) R0 = 17/18 R1!0 = size of block (20) R1!4 = task handle of dying task R1!12= 0 R1!16= &400C3 Issued by the Wimp when a task calls Wimp_CloseDown (if a task calls OS_Exit prematurely, the Wimp will call Wimp_CloseDown for it). The Task Manager module is again the main client of this message. &400C4 Message_SlotSize (broadcast) R0 = 17/18 R1!0 = size of block (28) R1!4 = task handle of task owning current slot R1!12= 0 R1!16= &400C4 R1!20= new current slot size R1!24= new next slot size This message is broadcast by the Wimp whenever Wimp_SlotSize is used to alter the amount of memory owned by a task. It is normally picked up by the Task Manager module to allow it to maintain its display of memory allocation. This message should not be acknowledged, since that would stop any other utilities from picking it up. &400C5 Message_SetSlot R0 = 17/18 R1!0 = size of block (28) R1!12= 0 R1!16= &400C5 R1!20= new current slot size R1!24= task handle of task whose slot should be changed This message is sent to a task by the Task Manager when the user drags the task's slot, if the task has initially told the Task Manager that it can deal with dynamic drags by acknowledging a message of this form when it started up. On receipt of this message, the task should (if R1!20 >= 0) call Wimp_SlotSize to alter its slot size to the appropriate value. See Wimp.Switcher for further details. &400C6 Message_TaskNameRq R0 = 17/18 R1!0 = size of block (24) R1!12= 0 R1!16= &400C6 R1!20= task handle of task being asked about If a task wishes to find out the name of a task given its handle, it should broadcast this message. If the Task Manager is running, and it recognises the task handle, it will reply with the following message: &400C7 Message_TaskNameIs R0 = 17/18 R1!0 = size of block R1!12= myref of previous message R1!16= &400C7 R1!20= task handle of task being asked about R1!24= task's slot size R1+28..= (0-terminated) This message pair is used by the !Help application so that it can provide extra help about the ROM modules (which have defined names). Data Transfer Protocol ---------------------- 1 Message_DataSave R0 17 (usually) R1!0 size !12 0 !16 1 ; DataSave !20 destination window handle ; !24 destination window icon ; copied from !28 destination x coord (screen coords) ; Wimp_GetPointerInfo !32 destination y coord (screen coords) ; !36 estimated size of data, in bytes !40 file type of data !44 proposed leaf-name of file, 0-terminated 2 Message_DataSaveAck (save data to file) R0 17 (usually) R1!0 size !12 my-ref field of DataSave message !16 2 ; save data to here !20 destination window handle ; !24 destination window icon ; preserved from !28 destination x coord (screen coords) ; Message_DataSave !32 destination y coord (screen coords) ; !36 estimated size of data, in bytes ; -1 if file is 'unsafe' !40 file type of data !44 full-name of file, 0-terminated Where this message is used as part of the scrap transfer protocol (see below), the 'estimated size' field is set to -1 by the sender, to tell the receiver that his file will NOT be 'safe' after it has been saved to the destination. Typically a file called will be saved, and it is not considered a good idea to put '' in the title bar of the document that has just been saved, or to mark it unmodified, since the scrap file will be deleted after the sender gets back a DataLoad (see below). 3 Message_DataLoad (drag file from Filer / I have saved data to a file) R0 18 (usually) R1!0 size !12 my-ref field of DataSaveAck message (or 0 if from Filer) !16 3 ; load data from here !20 destination window handle ; !24 destination icon handle ; copied from !28 destination x coord (screen coords) ; Wimp_GetPointerInfo !32 destination y coord (screen coords) ; !36 estimated size of data, in bytes !40 file type !44 full path-name of file, zero-terminated The filer sends this message when a file has been dragged into a window belonging to another application. The application is then free to copy or insert the file, if it so desires. If the application can load files of the relevant type, and the file is loaded successfully, it should reply as follows: 4 Message_DataLoadAck R0 17 (usually) R1!0 size !12 my-ref field of DataLoad message !16 4 ; DataLoadAck !20 destination window handle ; !24 destination icon handle ; copied from !28 destination x coord (screen coords) ; Wimp_GetPointerInfo !32 destination y coord (screen coords) ; !36 estimated size of data, in bytes !40 file type !44 full path-name of file, zero-terminated 5 Message_DataOpen (broadcast for double-clicked file) R0 18 (usually) R1!0 size !12 0 !16 5 ; destination info request !20 window handle of directory viewer !24 unused !28 x-offset of icon being opened within viewer !32 y ; allows for 'zoom' box if implemented !36 estimated size of data, in bytes !40 file type !44 full path-name of file, 0-terminated. DataLoadAck is returned by the application which loads the file. 6 Message_RAMFetch (transfer data to buffer in my workspace) R0 18 (error message if not acknowledged) R1!0 size !12 my-ref field of DataSave message !16 6 ; RAM fetch. !20 buffer address !24 buffer size (bytes) 7 Message_RAMTransmit (I have put some data in a buffer in your workspace) R0 18 (error message if not acknowledged) R1!0 size !12 my-ref field of RAMFetch message !16 7 ; RAM transmit. !20 buffer address ; copy of value sent in RAM fetch !24 number of bytes written to buffer (if buffer not full, send another RAMFetch) To write the data into the receiver's buffer, use the following call: Wimp_TransferBlock Entry: R0 = task handle of source R1 --> source buffer R2 = task handle of destination R3 --> destination buffer R4 = buffer length buffer addresses and length are byte-aligned (not nec. word-aligned) if the buffer addresses are within application space, they are validated to ensure they are within the correct task Errors: "Invalid task handle" "Wimp transfer out of range" Application code for direct file transfer ----------------------------------------- NOTE: In all cases where an unknown message action is received by an application, it MUST ignore the message completely. Save file: 1. transmit DataSave message 2. if DataSaveAck returned, save file and send DataLoad Unless receiver is the Filer, the DataSaveAck would refer to "", and the estimated size field would be set to -1, indicating that the file is not 'safe'. Errors encountered during file saving are reported by the sender, and DataLoad is not sent. 3. if RAMFetch returned, send RAMTransmit and loop until done NOTE: all messages in this protocol apart from the DataSave should quote the other side's my_ref field in their your_ref fields, to ensure that the messages are acknowledged correctly. Receiver: 1. DataSave received 2. If data can be loaded from RAM, send back a RAMFetch (look at approx data size in DataSave message, but do not rely on its absolute accuracy, ie. be prepared for MORE data than that to be sent) If RAMFetch not acknowledged, load from a file (step 3) if RAMTransmit received, finished if buffer NOT filled, else send another RAMFetch and loop. if any RAMFetch other than the 1st is not acknowledged, report error - no need to check your_ref field if RAMFetch (18) used, since the RAMFetch will not be acknowledged if pipe break received, shut up quietly 3. If data must be in a file, return DataSaveAck "", setting the 'estimated size' field to -1. If the environment variable Wimp$Scrap does not exist, the error message " not defined" should be generated. If DataLoad received, load file, delete and return DataLoadAck Note that the your_ref field of the DataLoad tells the receiver whether the file is the scrap file. Minimal functionality is for the sender to only cope with DataSaveAck, and for the receiver to only cope with file-based i/o. If the receiver wishes to engage in RAMFetch operations, it should be prepared for the sender to be ignorant of that protocol - ie. it should be prepared to revert to the scrap file mechanism. Ramifications ------------- The main change to the spec is that all applications must be prepared to recognise DataSave, and return at least a DataSaveAck to , followed by acting on DataLoad (which they do anyway), and deleting the file after loading it, if the your_ref field of the DataLoad refers to their DataSaveAck message. Another change is that when files are saved onto the Filer, this action is followed by a DataLoad message being sent. Therefore the Filer must respond to the DataLoad message with a DataLoadAck (if the DataLoad your_ref field is correct). It might have been possible to shift the onus onto the saver of the data, by sending a DataLoad message to the unsuspecting receiver. However, this would entail the creation and deletion of a scrap file whenever the data is dragged onto the desktop background!