home *** CD-ROM | disk | FTP | other *** search
- Adding your own PopUp Handler
- =============================
-
- You may add your own PopUp handlers to the PopUp Server application, either
- to provide new PopUp types, or to provide a different implementation for an
- existing PopUp type.
-
- Your code may be written in any language from which you can get linkable
- AOF output (C, assembler). The basic procedure is as follows:
-
- Write the .c code for your handler, e.g. _ProgInfo.c
-
- Provide in this, an
-
- extern handler_info HandlerInfo_ProgInfo
-
- which describes your handler, and includes a pointer to it's entry
- function, etc. Then edit HandlerTab.c - add a line to the list:
-
- HandlerInfo_Proginfo,
-
- Edit PopUps.h - add a prototype for your HandlerInfo:
-
- extern handler_info HandlerInfo_ProgInfo;
-
- Compile this code, and link it with DeskLib 2.00 or later.
-
-
- Supplied functions/constants
- ============================
-
- The PopUp Server supplies a few special functions for you to use instead of
- DeskLib functions, or to do special PopUp-related things, as well as some
- predefined constants which you should use to make your code more easily
- fixed if changes occur. These are defined at the bottom of Server.h and are
- listed again below.
- DO NOT use any functions/variables that are not listed here!
-
- /* SendState
- * Packages the given PopUp-specific data section of the application params
- * into a message_PopUpState, and sends it back to the client task.
- */
- extern void SendState(void *statedata, int statesize);
-
-
- /* ImDragging
- * If you wish to start a drag operation in your handler, you MUST call
- * this function as you do so - this tells the server that you are the
- * handler to call back when the drag finishes - if you do not call this
- * then the server will not call you (and will fail to process the drag
- * finish event)
- */
- extern void ImDragging(void);
-
-
- /* SetIconText
- * Equivalent to DeskLib's Icon_SetText, with one VERY IMPORTANT difference
- * - it handles strings terminated with CR (13) instead of NUL (0), which
- * may be passed in from BASIC and assembler client tasks.
- * You therefore MUST use this version instead of Icon_SetText!!!
- */
- extern void SetIconText(window_handle w, icon_handle i, char *text);
- #define Icon_SetText SetIconText
-
-
- /* ShowStaticPopUp
- * If you are providing a static PopUp, you will need to open it at
- * the x and y position requested by the user. To make this easier,
- * and help to share such code, this function is provided, which simply
- * opens the given window at the given top-left position.
- * (i.e. use ShowStaticPopUp(ctrl->basewindow, ctrl->openx, ctrl->openy);
- *
- * This call will also repel your window approximately 64 OS units away
- * from the edges of the screen, which ensures that the iconbar is always
- * visible, and is generally much nicer than opening hard up against an
- * edge of the screen.
- */
- extern void ShowStaticPopUp(window_handle window, int openx, int openy);
-
-
- /* KillMe
- * Will kill off the current PopUp
- * If a PopUp wishes to let everyone know that it has closed, then
- * it MUST call KillMe(). This should only be necessary on event_CLOSE
- * Wimp events, or if a 'cancel' button is clicked, etc.
- * (You do not need to call this function if you are told to close with
- * a REASON_CLOSE)
- *
- * If you do not call this function, then you will continue to recieve
- * WIMP events, and will tie up one static-instantiation slot. (bad)
- *
- * VERY IMPORTANT NOTE:
- * This call removes your PopUp instantiation information, which means
- * after the call you cannot rely on the passed-in ctrl block and
- * private workspace any more. (The former may have been changed and the
- * latter WILL have been deallocated). This should therefore be the very
- * last thing in your code before you return control for the last time.
- */
- extern void KillMe(void);
-
-
- /* Template_RMAFind
- * Roughly the same as Template_Find
- * However it actually clones into malloc() and RMA static memory chunks
- * so that the indirected data is always paged in.
- * THIS SHOULD ONLY be called if your PopUp is to be shown as a MENU LEAF
- * (because otherwise you will most likely be overwriting/overwritten by
- * another PopUp in these static memory areas)
- * i.e. only use it:
- * if ((ctrl->appflags & APPFLAGS_ISLEAF) != 0)
- * If this is not the case, or if it is a Static PopUp, then use the normal
- * Template_Find or Template_Clone.
- *
- * This function only guarantees 1024 bytes of space for indirected icon
- * data. If you need more than this (shame on you!) you will need to
- * alter the constant at the top of Template.c
- */
- extern window_block *Template_RMAFind(char *name);
-
-
- /* For REASON_OPEN, the pollblock contains a PopUpOpen message.
- * The definition of this includes the message header, the PopUp handle,
- * then the application parameter block header, followed (at offset 48 into
- * the complete WIMP message) by the PopUp-specific data.
- * Note that the pollblock includes a word at the front (event type), so
- * this shifts our data to offset 52 within the passed pollblock,
- * i.e. ((int) pollblock)+52 is the base address of the PopUp specific data
- */
- #define POPUP_DATA_OFFSET 52
-
-
- For examples, see the enclosed source code, and preferably use it as a
- template/shell for your own code to ensure you do everything right.
-
-
- Your handler function
- =====================
-
- It should be farly straightforward to see what is going on in the supplied
- PopUp sources. The basics are as follows, though:
-
- You supply a single handler function, which is called with 4 parameters:
- R0 (parameter 0) = reason code
- R1 (parameter 1) = control block
- R2 (parameter 2) = private workspace
- R3 (parameter 3) = Wimp poll event description block
-
- These parameters are described below.
-
- Static PopUps, being 'permanent' windows (they only go away when explicitly
- closed), can possibly allow several of the same type of PopUp to be open at
- once (e.g. both Draw and Edit could be displaying a FontSelect at once)
-
- Thus, static PopUp handlers should be able to handle multiple instantiations.
- To help this along, your handler is called with a different control block
- and workspace area for each PopUp type - USE THEM! Do NOT store window-specific
- data in static storage- use the provided workspace block.
-
-
- Reason code
- -----------
-
- This number tells your handler function why it is being called. Currently
- there are 3 reason codes defined (plus some proposed ones). They are:
-
- Reason code = 0 (open)
- You must create a new PopUp window according to the data passed in
- the Wimp poll event description block (which contains a complete
- Message_PopUpOpen - popup specific data starts at (event block) + 48)
-
- You should fill in appropriate sections of the control block (see below)
- such as the window handle and the poll mask before you exit.
-
- To exit, you return TRUE if you succeeded in creating the PopUp, else FALSE
-
- MENU LEAF PopUp
- Ensure the window does not have a close icon
-
- Duplicate the template using Template_FindRMA - if you do not do this,
- the WIMP stupidly looks in the wrong place for indirected icon data
- in the wrong application's workspace, and will crash your client!
-
- Create the window, but DO NOT SHOW IT - the server will do this for you.
-
- MENU STANDALONE PopUp
- Ensure that the window does have a close icon
-
- If you do not supply a STATIC PopUp, then you may use Template_Find
- to save memory - otherwise, you must use Template_Clone.
-
- Create the window, but DO NOT SHOW IT - the server will do this for you.
-
- STATIC PopUp
- Use Template_Clone to create your windows (though Template_Find will
- suffice if the window contains NO indirected data)
-
- Create AND OPEN the window. (Statics may use panes, so the server
- can't make assumptions about how to open the PopUp for you)
- Use ShowStaticPopUp() to open the window, to share existing code.
-
- Reason code = 1 (Close)
- Simply Wimp_DeleteWindow your window. You MUST NOT close the menu tree,
- as this call is used to remove your PopUp as the user moves the mouse
- from one menu item to another!
- Remember to call KillMe();
-
- Reason code = 2 (Wimp Event)
- You must try to process the Wimp event passed to you (parameter 3).
- If you succeed in processing the event, return TRUE, else FALSE.
- Note that you may get events intended for OTHER PopUps - you MUST check
- if the event really applies to the PopUp window referenced in the control
- block, and return FALSE if it is not your window!
-
- Events will only be given to you if your poll mask allows it.
- Events you fail to handle (and NULLs) will be passed on to the next
- PopUp handler until somebody handles them. If nobody handles it, a default
- action may be performed by the server (see below).
-
- IMPORTANT NOTES
- 1 If your window is not 'auto-redraw', you MUST supply a redraw handler,
- or else an attempt to open your PopUp will result in the machine
- locking up. (Check also that you have enabled event_REDRAW)
-
- 2 If you ever start a Wimp drag operation in your event handler, you MUST
- invoke
- ImDragging();
- so that the server knows where to deliver the related drag-finish event.
- If you don't call this function, the drag-finish event will NOT be
- delivered to you.
- In your event_USERDRAG handler, you can assume that the event IS yours,
- as you'll only ever get this event if you call ImDragging as you
- start a drag. Obviously, you should only call ImDragging if you start
- a drag!
- (See _SaveAs.c for an example of a PopUp using drags)
- P.S. Please use Icon_DragASprite where possible (code is already linked
- into the application, and DragASprite looks good - it will do an
- ordinary drag for you under RO2, or if DragASpr is not configured on)
-
- 3 If nobody handles the event, the following default action is taken:
- event_OPEN: Wimp_OpenWindow(&event->data.openblock);
- event_KEY: Wimp_ProcessKey(event->data.key.code);
-
- 4 If the event causes you to close the PopUp, then remember to call
- KillMe() to let the server know the PopUp is closed.
-
- 5 VERY VERY important - Menu PopUps
- Whenever you delete your window, you MUST ensure that the menu
- 'containing' your window has been closed. In many circumstances you
- can just Wimp_CreateMenu((menu_block *) -1, 0, 0); to kill the menu
- before Wimp_DeleteWindow(), but in some cases you should check
- if your window is open - if it IS open, you need to kill the menu
- before you can Wimp_DeleteWindow.
-
- Failure to Close the menu first will result in the WIMP crashing.
- Closing when it has been closed may result in you killing off another
- (unrelated) menu (e.g. if your window is closed by a click outside the
- window, that click could create a NEW menu before you are called to
- close the window)
-
-
- Control Block
- -------------
-
- This contains some useful information about how to open the PopUp, and
- is where you must store relevant information for the server to use.
- The control block is laid out as follows:
-
- event_pollmask pollmask - You must keep this updated with a Wimp_Poll
- style PollMask - mask out all events you
- don't want, for efficient operation.
- window_handle basewindow; - You must store the (BASE) window handle
- here for the Server to use.
-
- task_handle clienttask; - read-only: The client's taskhandle
- int openx, openy; - read only: The x/y position you should
- open the window at (top left corner)
- char appflags; - read-only: The application flag byte
- as described in the application parameter
- block details.
-
- NOTE that you will get one such work area for EACH PopUp INSTANTIATION
- that you are controlling (i.e if the server asks you for 2 static PopUps,
- you will be called with two different ctrl and private workspace blocks)
-
-
- Private Workspace
- -----------------
-
- In the structure used to link your handler to the server, the last item
- is a 'private workspace size'. For each PopUp requested, a new chunk of
- memory is allocated for the relevant handler to use, and is passed in to
- that handler as it's private workspace.
-
- NOTE that you will get one such work area for EACH PopUp INSTANTIATION
- that you are controlling (i.e if the server asks you for 2 static PopUps,
- you will be called with two different ctrl and private workspace blocks)
-
- (See _Magnify.c for an example PopUp which uses the private workspace
- to provide multiple STATIC (and 1 MENU) instantiations)
-
-
- Event data
- ----------
-
- This is a normal DeskLib event_pollblock structure. That is, the first
- word contains the reasoncode returned by Wimp_Poll, and the remainder
- of the block contains the event-specific data returned by that SWI.
-
- It comes to you in entirely uncensored form. If you do not handle the
- event, or if it is a NULL event, you MUST return with the block unchanged.
-
-
- Adding your own PopUp Server
- ============================
-
- The PopUpManager module has the ability to use a different aplication as
- a server for each PopUp type it knows of. This allows you to write new
- server application(s) which replace old PopUps and/or provide new ones -
- in this way, you can add assembler or BASIC handlers without having to
- be able to link them into the supplied server application.
-
- A PopUp server may also be a relocatable module, which may happen in the
- future with the base set of standard PopUps. The PopUp interface has been
- carefully designed to go through the manager module to allow this sort of
- flexibility in how PopUps are served.
-
- A PopUp server is very simple to write, especially if you write a dedicated
- server for each PopUp (minimising the amount of generic 'handle multiple
- PopUp types' code you have to write).
-
- It is basically a WIMP application which includes PopUp handler(s).
- When it starts up, it registers each handler in turn with the PopUpManager
- (SWI PopUp_Register), replacing any existing handlers for those PopUp types.
- On exit, it calls PopUp_Deregister for each supplied handler to inform the
- manager that they are no longer supported by a server.
-
- The supplied PopUp Server plus two PopUps were written in less than a day.
- (Though admittedly, I had written similar things a few times before during
- development of the system, so knew exactly what to do!)
-
- The server must provide a list of PopUp instantiations, indexed by the
- PopUp handle that the PopUp Manager generates on PopUp_Open. Of course, if
- you provide only a single Menu PopUp, you need not hassle yourself with
- multiple instantiations etc.
-
- When the server recieves a Message_PopUpOpen, a Message PopUpClose, or
- a WIMP event, it adjusts its lists appropriately, and calls the appropriate
- handler with a reason code of 0 (open), 1 (close) or 2 (Wimp event).
-
- When processing Wimp Events, you should check for important events such as
- a quit message, and if you then have not processed the event, pass it on to
- the handlers - use of an event mask for each handler can make this quite
- efficient. Pass the event around ueach instantiation until a handler has
- handled it (though pass NULLs to all handlers which haven't masked them out)
-
- After calling the (0) Open Handler, you must check if the PopUp is a Menu
- PopUp - if it is, you must do the following:
- IF PopUp is NOT a menu leaf THEN
- SYS "Wimp_CreateMenu",,popupwindow, openx, openy
- ELSE
- Send PopUpRequest message to client task with
- message!20 = popupwindow
- message!24 = openx
- message!28 = openy
- ENDIF
-
- The last detail is that the WIMP was not designed with PopUps in mind, and
- so the PopUp Manager has been designed around several rather difficult
- features (all of which are perfectly reasonable under normal use).
-
- One, you see above - the WIMP won't let us attach our window to another task's
- menu tree, so we must (currently) request that the application attaches the
- window on our behalf using the PopUpRequest message.
-
- The only other one that need concern you is that the WIMP assumes that any
- window in the menu tree belongs to the menu's creator - this would be fine,
- except that it means that when looking for indirected data, the WIMP looks
- in the WRONG application's memory slot! This has suitably undesirable effects.
- The only way to fix this (currently) is to allocate enough memory in the RMA
- to hold all indirected data. Luckily, very little is needed, as the only time
- this is a problem is with MENU LEAF PopUps. As only one such PopUp is ever
- open, we only ever need to store one such PopUp's data in the RMA.
-
- (Standalone MENU and STATIC PopUps work fine, as the whole window/menu-tree
- belongs to the PopUpManager in these cases)
-
-