category: Specification <notextile> <div align="center"> <table cellpadding=2> <tr><th align="right">Document Ref:</th> <td align="left">1309,419/FS</td> <tr><th align="right">Project:</th> <td align="left">Shared Source RISC OS release (formerly Ursula and Java 1.2)</td> <tr><th align="right">Revision:</th> <td align="left">G *** DRAFT ***</td> <tr><th align="right">Date:</th> <td align="left">22 February 2015</td> <tr><th align="right">Author(s):</th> <td align="left">Ben Avison</td> </table> </div> <div id="toc_heading"></div><div id="toc"></div> <h2>Overview</h2> <p /> <h3>This Document</h3> <p /> This document supersedes the cut-and-paste and drag-and-drop protocol application notes [1] and [2], and specifies the cut-and-paste / drag-and-drop abilities to be added to the Wimp, plus the Clipboard module that supports the Wimp (and whose facilities will also be of use to future applications intended to support the protocols). <p /> Key terms are defined and some familiar terms are also redefined more precisely in the glossary (§13), and the reader is recommended to read this first. <p /> Where information is fundamentally new in this specification - non-obvious consequences of and clarifications and extensions to the existing protocol, <u>the relevant section is underlined to bring attention to the fact.</u> <p /> The document may be slightly weighted towards text-handling applications, but this is because the user interface is generally more complicated in such cases. It is expected that the reader be able to extrapolate meanings to apply to any possible fundamental type of data. <p /> <h3>Cut-and-Paste</h3> <p /> Global-clipboard-based or cut-and-paste data transfer involves data being removed or copied from any document in the desktop to a notional "clipboard", then pasted from the clipboard into the same document, or any other document in the desktop, whether managed by the same application or not. On the way, data translation is performed in such a way as to minimise the information loss about the data. <p /> This interface involves three operations, cut, copy and paste, which may be performed in any order. Any one data transfer will require at least two of these operations, in addition to the choice of the original selection and the destination point; the process is somewhat clumsy (and unintuitive, since the clipboard is hidden from view), so this is the least preferred technique of the two described in this document. However, it must still be provided, as it does allow some operations which cannot be achieved in any other way, and can perform other operations faster than by drag-and-drop. <p /> <h3>Drag-and-Drop</h3> <p /> Drag-and-drop is similar to cut-and-paste, but with the cut/copy performed by pressing a mouse button, and the paste by releasing the button at the destination. Full drag-and-drop compliance combines the features of conventional, simple drag-and-drop, as commonly used in Save dialogue boxes, with the data translation abilities of the global clipboard, and overcomes the abstract nature of the global clipboard by the displaying throughout the drag a bounding box, dithered sprite/object or representation of the insertion point. <p /> The user interface is simpler to use - consisting typically of two mouse drags (one to select and one to move or copy), with a requirement for at most one keypress (the Shift key swaps the meaning of copying and moving). However, the programming interface is more complicated, because continuously negotiated transferable data types, destination positioning and rendering of objects and pointers are required in addition to everything needed for cut-and-paste. This complexity is possibly responsible for the low implementation rate of the protocol to date. <p /> <h3>General</h3> <p /> The Clipboard module is primarily to enable cut-and-paste and drag-and-drop to be reliably implemented for writable icons, which are handled automatically by the Wimp. (The fundamental problem is that the established cut-and-paste and drag-and-drop systems are Wimp-message-based, and the Wimp itself is poorly equipped to send and receive messages.) <p /> However, the module is secondarily to handle the complex protocols on behalf of any application that chooses to do so - and in the process, producing a more uniform user interface. This is to be the preferred method of implementing the protocols in future, although in special cases, the tasks it performs can be split into four separate areas, any combination of which can be taken advantage of by the same application: <ul> <li>clipboard management - supporting cut and copy operations</li> <li>clipboard procurement - supporting paste operations</li> <li>sending drag-and-drop data</li> <li>receiving drag-and-drop data</li> </ul> <p /> <h2>Outstanding Issues</h2> <p /> <h3>Bounding Box Discrepancies</h3> <p /> It is possible that data may have different "real life" bounding boxes in different data types - for example, a DrawFile sprite object may be transformed and/or scaled, and thus have a different bounding box to the underlying sprite. Thus if a transformed sprite object were dragged from Draw to a sprite editor window, the bounding box would <i>not</i> represent the final position of the sprite. <p /> <h2>Technical Background</h2> <p /> <h3>This Document</h3> <p /> Some important pre-existing technical terms are rigorously defined in the context of cut-and-paste / drag-and-drop in the Glossary in §13, along with some new terms introduced in this document. <p /> Where technical background information is relatively straightforward (no more than one or two short paragraphs), it is included alongside the appropriate part of §4 or §5, for ease of reference. <p /> <h3>Previous Documents</h3> <p /> Simple drag-and-drop operations, such as those employed by Save dialogue boxes, do not employ any inter-task negotiation during the drag, and use the plain DataSave/DataLoad protocol during the drop, as described in the Programmer's Reference Manual [3]. <p /> The Style Guide [4] first indicates selection models, then describes an overview of cut-and-paste and drag-and-drop behaviour, before referring the reader to the relevant Support Group Application Notes [1] and [2]. <p /> <h3>Previous Applications</h3> <p /> Old-style selection model / copy-and-move implementations are still in existence, especially so in the case of text editors, (e.g. Zap, StrongEd, SrcEdit) which have often followed Edit's example. Such schemes typically involve only three actions to perform an operation (select region, position caret, move/copy keypress) rather than the four (select region, cut/copy keypress, position caret, paste keypress), but have the disadvantage that they can present both a caret and a selection to the user at the same time, which is potentially confusing. Old behaviour will remain deprecated, but new cut-and-paste / drag-and-drop applications must be able to interact with tasks that use it. <p /> Other applications may support just cut-and-paste, or just drag-and-drop. Drag-and-drop will be the favoured technique in future, due to the simpler actions required (select region, drag region), but cut-and-paste must also be supported as well, to cater for cases when drag-and-drop cannot be used (e.g. when copying on to a menu tree). <p /> Some aspects (e.g. pointer shape, window) of applications already written to the application note guidelines (e.g. DataPower, EasiWriter/TechWriter) are already inconsistent, due to the lack of detail in the application notes. Applications will in future be encouraged to follow the more detailed specification herein. <p /> <h2>User Interface</h2> <p /> <h3>Selection</h3> <p /> <h4>Protocol</h4> <p /> <h5>Rendering</h5> <p /> <u>Selection is rendered either by a recolouring an object (with its photographic negative or otherwise) or by drawing a bounding box, typically in red, and optionally with one or more "handles" for resizing and/or rotating operations as appropriate:</u> <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic4.gif" alt="" align="middle" height=60 width=103 /><img src="/images/risc_os_open/specifications/clipboard/Pic6.gif" alt="" align="middle" height=60 width=123 /><img src="/images/risc_os_open/specifications/clipboard/Pic5.gif" alt="" align="middle" height=60 width=146 /><img src="/images/risc_os_open/specifications/clipboard/Pic7.gif" alt="" align="middle" height=60 width=111 /> <p /> It should be emphasised that a caret must never appear within the same window as a selection at any time, not even during the selecting drag. Placing a new caret or selection removes any caret or selection previously active in the same window. (The definition of a window for these purposes is a top-level window and its panes and all their child windows.) <p /> <u>However, if during (or immediately after) the selection process, the selection would have to be drawn with zero width (i.e. for text selections, when the two ends snap to the same character boundary), a caret must be displayed instead.</u> It is helpful to consider the caret as a zero-width selection; only one selection may be present within one window at a time, so the exclusivity of the caret and selection is an extension of this concept. <p /> <u>When either a caret or a selection is placed in a document, the window must gain the input focus.</u> This will happen automatically for a Wimp-drawn user caret, but in the case of application-drawn carets and selections, the application must position the Wimp caret in the window, but marked as invisible, in order to achieve the same effect. Simply changing the window border colour (as is possible in Wimps since RISC OS 4) is not acceptable. <p /> When a caret or selection is placed in a different drag-and-drop window, the old selection must be <u>redrawn as a shaded selection, not left as is or removed entirely</u>. The caret must be removed entirely <u>(or optionally redrawn as a shadow caret)</u>; if the application uses a Wimp-drawn user caret, the caret will be removed for it automatically. The LoseCaret and GainCaret events must not be used to determine when this is necessary, as the Wimp may "borrow" the caret temporarily while a menu is open. A Wimp message exists to indicate when removal or redraw of the caret and selection is necessary, and must be used in preference to the events (see §5.1.1). <p /> <u>Note that a selection may also be non-shaded but not have the input focus if an application not adhering to the cut-and-paste / drag-and-drop protocols had grabbed the Wimp caret (and therefore the input focus). Similarly, non-Wimp-drawn carets may be deprived of the input focus under similar circumstances while neither being removed, nor being replaced with a shadow caret.</u> <p /> <h5>Mouse Events</h5> <p /> <u>Non-contiguous selections (just about everything except text and DTP documents) will continue to be handled as described in the Style Guide [4], with the proviso that clicking Select over an already-selected object must not deselect anything, as a Select click event always precedes the Select drag event which initiates a drag-and-drop operation. Appropriate action must also be taken to un-shade shaded selections when necessary.</u> <p /> On the other hand, a more detailed behaviour for contiguous selections must be adhered to in future. In summary: <ul> <li><i>Select</i> click outside the selection (or when there is no selection, or at one end of a selection): position the caret at the pointer position, and flag the next <i>Select</i> drag as creating a selection.</li> <li><i>Select</i> click on a selection: <u>if the selection was shaded, un-shade it.</u> <u>Make sure the window has the input focus.</u> Flag the next <i>Select</i> drag as being a drag-and-drop drag.</li> <li><u><i>Select</i> click in a "dead" region of a window (e.g. in a page border): un-shade any selection or replace any shadow caret with the caret, if either exists. Make sure the window has the input focus. Optionally, flag the next <i>Select</i> drag as causing an window scroll operation (as Impression, TechWriter etc. do as present), but certainly not as starting a selection or drag-and-drop operation.</u></li> <li><i>Select</i> drag-start event: <u>remove the caret</u>, and set the selection from the old caret position to the current pointer position. Alternatively, start the drag-and-drop operation (see §4.4.1). The exact meaning is determined by the flag that was set at the <i>Select</i> click stage.</li> <li>During <i>Select</i> drag: if creating a selection, adjust the most recently touched end of the selection to the pointer position at regular intervals; <u>autoscroll the window if necessary, using the SWI Wimp_AutoScroll introduced in the RISC OS 4 Wimp.</u> For what to do during a drag-and-drop drag, see §4.4.1.</li> <li><u><i>Select</i> double-click: select a word (as defined in the Style Guide), irrespective of whether the click is on an existing selection or not.</u></li> <li><u><i>Select</i> click-drag (button pressed, then released, then pressed again within the double-click limits, then held or moved according to the drag limits): equivalent to a normal selection-delimiting drag, except that the selection limits are rounded to word boundaries (excluding whitespace at either end).</u></li> <li><u><i>Adjust</i> click when there is no caret or selection: position the caret at the pointer position, unless there was a shadow caret, in which case, position the caret where the shadow caret was. Set a flag to indicate that there was no caret or selection before the <i>Adjust</i> click (the shadow caret doesn't count); do not rely on the fact that there is no selection displayed when the drag event is generated to flag this, as a zero-width selection may have been displayed as a caret instead.</u></li> <li><i>Adjust</i> click when there is a caret: <u>remove the caret</u>, and set the selection from the old caret position to the current pointer position.</li> <li><i>Adjust</i> click when there is a selection: grow or shrink the selection so that the <i>nearest end</i> of the selection moves to the pointer position. <u>(Remember to un-shade the selection and/or gain the input focus if necessary.)</u></li> <li><u><i>Adjust</i> click in a "dead" region of a window: the same as Select in these circumstances.</u></li> <li><i>Adjust</i> drag-start event: <u>unless there was no caret or selection before the preceding <i>Adjust</i> click,</u> adjust the most recently touched end of the selection to the pointer position.</li> <li>During <i>Adjust</i> drag: <u>unless there was no caret or selection before the preceding <i>Adjust</i> click,</u> adjust the most recently touched end of the selection to the pointer position at regular intervals; <u>autoscroll the window if necessary, using SWI Wimp_AutoScroll.</u></li> </ul> <p /> Other operations (including <i>Adjust</i> double-clicks, higher-multiple-clicks and combinations with shifting keys) are left to the application to respond to as it sees fit - they might select a line of text, or select something in another layer, or whatever. Typically, higher-multiple clicks of <i>Select</i> will select progressively larger blocks of text. For single-line items such as writable icons, three clicks means select the entire line. Once the maximum number of clicks is reached, the next click is interpreted as for a single click, so for writable icons, a quadruple-click sets the position of the caret. <p /> In order to make selections over a larger area than can be displayed in a window, during selecting drags of contiguous selections and select box drags of non-contiguous selections, autoscrolling can be implemented. However, since there is rarely a meaning to making a selection spanning several windows, there is only one meaning to moving the pointer off the window, and so there must be no need for a pause over the autoscrolling zone to precede commencement of scrolling, as this would merely slow down the user's actions. <p /> <h5><u>Keypresses</u></h5> <p /> There are some special keypresses relating to cut-and-paste that affect the selection. Obviously, these only apply to selections that have the input focus (and therefore never apply to a shaded selection). The keypresses are: <ul> <li>Ctrl-Z: clear the selection (i.e. undraw the highlights), and place the caret (if appropriate) at the right-hand end of the old selection (or the left-hand end in a right-to-left language).</li> <li>Ctrl-V or Insert: delete (not cut) the selected data, and place the caret (if appropriate) at the end of the newly inserted text.</li> <li>Ctrl-X, Backspace or Delete: cut the selected data and place the caret (if appropriate) where the selection was.</li> <li>Ctrl-K: delete (not cut) the selected data and place the caret (if appropriate) where the selection was.</li> </ul> <p /> Then there are a number of special behaviours for textual regions: <ul> <li>Left-arrow/up-arrow: clear the selection, and process the keypress as though the caret had been at the left of the selection.</li> <li>Right-arrow/down-arrow: clear the selection, and process the keypress as though the caret had been at the right of the selection.</li> <li>Any other repositioning keypresses (Home, Tab etc.) behave along similar lines, as appropriate to the application.</li> <li>Any other keypresses that would normally insert one or more characters: perform a cut operation, then position the caret where the selection was, and process the keypress as normal.</li> </ul> <p /> Any other keypresses must not affect the selection. <p /> During drags (both those that set a selection and those that copy or move one), no keypresses that would normally affect the selection must be acted upon. <p /> <h5><u>Scope</u></h5> <p /> When a caret or selection is placed in the same window where one already exists, the old one is removed (not just re-rendered as a shaded selection). <u>In order for this to be consistent with the use of input focus colouring of windows, all carets and selections must be unique within a group of windows characterised thus: a top-level (non-nested) window, all its panes, and all windows nested within the window or one of its panes. If a task does its own selection handling but the window or one of its panes also uses writable icons, the task will need to monitor caret/selection updates to the writable icons in order to deselect its own selections.</u> <p /> Carets and selections must not be preserved when a window is closed, deleted or iconized (check for Open_Window_Requests with handle-to-open-behind of -3 to detect iconization). The Wimp takes care of everything for Wimp-drawn carets, and automatically removes the input focus in any case. If a selection can be made in a dialogue box opened from a menu, then the task must act as though the window were being closed when receiving Message_MenusDeleted, as tasks are not sent the usual Close_Window_Request for such windows. <p /> When the window is being closed or deleted, application-drawn carets and selections must be marked as absent, but when it the window is being iconized, carets and selections drawn by the application must be flagged as a shadow caret (if supported) or a shaded selection, respectively, ready for the next redraw request. <p /> <h4>Clipboard Module</h4> <p /> The Clipboard is not involved in the selection process. <p /> <h4>Writable Icons</h4> <p /> Up to one writable icon selection may exist in each window, and the selection will only be un-shaded if the window has the input focus. <p /> <h5>Rendering</h5> <p /> Carets within writable icons will be Wimp colour 11 (red), irrespective of the background colour of the icon. This will be achieved by using (Wimp colour 11 EOR background colour), calculated in GCOL space, as the colour to EOR on to the icon. <p /> Selections and shaded selections will be drawn by switching the foreground and background colours, then fading them if appropriate. A gap of 4 OS units will be left before the top and bottom borders (if any) of the icon. Therefore, a typical writable icon will look like this in its three states: <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic8.gif" alt="" align="middle" height=140 width=182 /> <p /> Using this method is better than EORing a block of colour, especially in the shaded selection case, where the anti-aliasing of the text is destroyed by an EOR operation. It also means that non-standard writable icons are catered for sensibly as well with no extra effort: <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic9.gif" alt="" align="middle" height=126 width=282 /> <p /> In the past, during writable icon redraws caused by scrolling of the icon (caused, for example, by repositioning of the caret), there has been a certain amount of flicker, both of the text, and of the caret itself, especially for large writable icons. This will be exaggerated substantially if the same technique is used to draw selections; to reduce flicker in both cases, a new algorithm will be written to deal with icon updates following caret / selection / ghost caret changes, utilising block copies wherever possible. <p /> <h5>Scrolling</h5> <p /> Icons where the text is less wide than the icon are relatively simple; the text has a fixed position, irrespective of caret and selection position. But it is likely that where the text is wider than the icon, occasions will arise where the user needs access to areas of the text string that are normally hidden, in order to set one or both ends of a selection. The matter is similar to the requirement for icon scrolling to position the ghost caret during a drag-and-drop selection (see §4.4). <p /> So, while the user is delimiting a selection, or when a ghost caret is displayed in the icon, an autoscrolling scheme will be followed, directly analogous to that used for windows in Wimp_AutoScroll. <p /> Note in particular: <ul> <li>The speed of scrolling is proportional to the distance the pointer has moved beyond the inside edge of the autoscrolling "pause" zone. This is because this scheme allows fine user control of both acceleration and deceleration.</li> <li>When delimiting a selection, autoscrolling will start as soon as the pointer enters the "pause" zone - i.e. a pause time of zero is used. Conversely, to start autoscrolling during a drag-and-drop operation, the pointer must be held over the pause zone for the configured pause time. This matches the equivalent behaviour for autoscrolling of windows.</li> <li>While document windows are generally of a comparable size, hence the similar pause zone widths, the size of writable icons can vary dramatically from icon to icon - compare, for example, a writable icon that is part of a numeric field, with the URL at the top of a web browser window. Scrolling speeds that would suit a small icon would be painfully slow for a very large one, and usable speeds for a large icon would scroll a small icon far too quickly. Therefore, the scrolling speed of a writable icon when the pointer is at one end will be proportional to its width. However, it is also desirable that the scrolling speed ramp up at the same rate, irrespective of icon size; these two constraints imply that a fixed proportion of the width of any icon needs to be allocated as the autoscroll pause zone - we will use 1/4 of the width at each end, as illustrated to scale below:</li> </ul> <p /> <img src="/images/risc_os_open/specifications/clipboard/Pic10.gif" alt="" align="middle" height=344 width=575 /> <p /> Below, the autoscrolling zone is cross-hatched; the autoscrolling pause zone is the intersection of the autoscrolling zone with the icon bounding box: <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic22.gif" alt="" align="middle" height=133 width=268 /> <p /> <h5>Mouse Events</h5> <p /> Mouse events in writable icons will follow the general behaviour, as specified in §4.1.1.2, but with a couple of slight changes. The definition of a word will match that used for Shift-arrow navigation, i.e. treating both spaces and the '.' character as word delimiters. <p /> On the second click of a double click with Adjust, the selection established by the first Adjust click will be extended outwards at both ends to include complete words. <p /> Clicks with either Select or Adjust will not affect the text origin, unless they are setting the caret position (which will still be centred as far as possible, for consistency with old Wimps). Neither double-click operation will affect the text origin either, unless a scroll was caused by the first click of the two. <p /> During a drag, while the pointer is over the central zone between the autoscrolling zones, no scrolling occurs. The autoscrolling zones act just like those of windows. After each scroll step (<i>not</i> before), the selection end is determined by the closest character boundary to the pointer. <p /> When a drag starts, any movement of the text which was performed at the time of the click event is undone. This is necessary because otherwise we have introduced a relative movement between the text and the pointer which was not intended by the user, and the alternative (moving the pointer) is less in the style of the RISC OS user interface. Consider, for example, if the user clicks Select at the right hand end of an icon where there is a lot of text further to the right which is clipped out of view: if the user starts dragging to the left, but as a result of the initial click, the text had jumped quickly to the left of the pointer and so the user is now creating a selection to its right; worse still, if the pointer is still over the autoscrolling zone, the initial character may start scrolling off the left of the icon, leaving a large selection in the opposite direction to that intended by the user! <p /> <h5>Keypresses</h5> <p /> These will in general be handled as in §4.1.1.3. Note in particular: <ul> <li>Only keypresses as specified in the validation string would normally insert characters, so any others (except Ctrl-X and its synonyms, of course) will not cut any selected text.</li> <li>Whenever a keypress (including Ctrl-X and synonyms) causes the caret to be repositioned, a traditional, centred caret will be used.</li> <li>When a paste is performed, and so an entirely new selection is set, the selection will be centred within the icon (unless it is wider than the icon, in which it will be right-aligned).</li> </ul> <p /> <h5>Wimp Selections and Menus</h5> <p /> When the pointer moves over a writable menu item, or when a dialogue box containing writable icons is opened from a menu, the Wimp automatically places the caret in the menu item, or the first writable icon, respectively. The Wimp remembers the position of the caret before it does this, and then returns the caret to its old location afterwards. <p /> This behaviour will be extended to check for Wimp selections that have the input focus before the caret is placed. If the same selection still exists afterwards (i.e. a selection has not been made within the menu structure in the meantime), then the input focus will be returned to it. <p /> Note that selections cannot be made in writable menu items, as any clicks are considered as choices from the menu tree before being considered as requests to set the caret position, let alone setting a selection. Also note that drags cannot be made to an icon in a menu structure, as the click that starts the drag will close the menu structure before the drag begins! <p /> Cut and paste will work as specified for writable icons in dialogue boxes in menu trees, and pasting (but obviously not cut or copy) will work for writable menu items. <p /> <h5>Password icons</h5> <p /> Cutting, copying and dragging from a password icon, or pasting or dragging into one, is not permitted for security reasons. To give the user some feedback, the Wimp issues a system beep if the user attempts to do so. Selecting text in a password icon is permitted, although the only action that can be performed on it is deletion. <p /> <h5>Application-altered Indirected Data</h5> <p /> On occasions, the text of a writable icon is altered by code other than the Wimp's writable icon handling code (and as a prerequisite, the text data has to be indirected). A common example of this is the writable numeric range, where adjuster arrows may be used to alter the value inside the accompanying writable icon. <p /> Altering the data does not, in itself, cause any screen updates to be done; applications have to force a redraw of the icon for the new value to be displayed. During the redraw, the caret is redrawn, but only using the last work-area-origin-relative co-ordinates calculated the last time the caret was positioned. If the new data requires a different text origin, the caret will then appear incorrectly positioned. To cater for this, nearly if not all applications set the position of the caret again, as well as forcing a redraw of the icon. <p /> A similar situation could arise with selections (and even ghost carets) - but since no existing applications know about selections, they will not be able to cater for the "feature" in the API. For example, suppose the value 99 was selected in a centred numeric range, then the up-arrow was pressed; the result would be as below: <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic1.gif" alt="" align="middle" height=59 width=138 /> <p /> To work around this, separate checksums will be kept for the text of the icon currently containing the selection and the ghost caret. Each time an icon is redrawn, a new checksum is calculated, and if the checksum has changed, the selection or ghost caret will be removed. This is because the change to the text has probably invalidated the selected text anyway. <p /> A variant on this approach will be used to fix the equivalent long-standing bug in the case of carets. One potential fix which we have to reject is to simply remove the caret when the text changes, because in many cases the application already has its own workaround whereby it reapplies the caret, so with each change of the text, the window's title bar would flicker due to losing and re-gaining the input focus. Instead, the Wimp will recalculate the caret position, assuming the same index into the string is required - unless the icon's numeric flag (icon flag bit 20) is set, in which the caret will be kept at the same index from the end of the string, to preserve the decimal place being edited. This way, future applications need not include the workaround at all. <p /> <h5>Scope</h5> <p /> In addition to the rules in §4.1.1.4., any combination of caret, ghost caret and selection must be removed when an icon is deleted. Also, when a menu is closed, any selection in a dialogue box linked to the menu must be removed (the caret already is removed in these cases). <p /> It will not be possible for any caret, selection or ghost caret to be placed in a writable icon that is shaded. If any caret, selection or ghost caret is present in a writable icon when it becomes shaded, they will be removed. <p /> The Wimp selection and both carets will be removed when the Wimp font is changed, but this will be the responsibility of the task that is changing the font - namely !Configure (or more precisely, a configure plug-in). <p /> If an icon is resized using Wimp_ResizeIcon, any of the caret, ghost caret and selection which are present in the icon will be marked absent (although no redrawing will occur immediately, because Wimp_ResizeIcon expects to be followed by a separate redraw operation anyway). <p /> <h5>Draggable-Writable (Type 14) Icons</h5> <p /> Type 14 (draggable) writable icons are much rarer than standard, type 15 writable icons, and in the past, have only differed in that drag events are reported to the task. Some applications (such as Fresco) have taken advantage of these icons to implement a simpler form of drag-and-drop; such behaviour would be broken if the steps described above were employed for type 14 icons. Type 14 icons could also be a useful special case, where sub-units of the information in the icon have no meaning on their own, and where only the entire text can logically be dragged-and-dropped. <p /> Therefore, all of the rest of §4.x.3 and §5.x.3 (with the exception of developments specific to carets, such as the bugfix in §4.1.3.7) will only apply to type 15 writable icons. <p /> <h3>Cut and Copy</h3> <p /> <h4>Protocol</h4> <p /> "Cut" and "Copy" menu options, if provided, must be placed as described in the Style Guide; the options must be shaded if there is currently no selection in the window. <p /> <u>A cut operation must be performed when the task receives a Ctrl-X, Backspace or Delete keypress (i.e. Wimp key codes &008, &018 and &07F) </u>or when "Cut" is chosen from the menu. When <u>a keypress suitable for inserting data is received, or when data is dragged-and-dropped on to the selection's window</u>, or pasted when a selection is active, the selection must also be cut prior to performing the raw operation. <p /> A copy operation must be performed when "Copy" is chosen from the menu, <u>or when the task receives a Ctrl-C keypress (Wimp key code &003) - but not when Wimp key code &18B is received, because although it resulted from a press of the "Copy" key on the Archimedes, A30x0, A4000 and A5000, on all other machines it will be generated by the "End" key.</u> <p /> Both cut and copy will cause a copy of the selected data to be placed on the clipboard overwriting any data already there. (See §13 for a definition of clipboard in this context.) No attempt must be made to render the clipboard; it is a hidden, abstract entity. The data on the clipboard is of indeterminate data type; a data type to use for the transfer is negotiated between the clipboard owner and the pasting task at paste-time, and may involve either or both tasks performing data translation. <p /> The only difference between cut and copy is that the selected data must be removed from the main document in the case of a cut operation. <u>The selection remains unchanged in the case of a copy operation (i.e. it is not deselected).</u> <p /> <u>If the data cut or copied to the clipboard is of type text, the newlines (if any) must be represented by ASCII &0A.</u> <p /> <h4>Clipboard Module</h4> <p /> The use, or not, of the Clipboard module to handle cut and copy operations will not affect the cut or copy user interfaces, even though this entails some complication of the programming interface (see §5.2.2). <p /> <h4>Writable Icons</h4> <p /> Keypresses will be honoured as described in §4.2.1 - although individual icons don't and shouldn't have menus, so the description of performing cuts and copies via a menu is inappropriate. The data held in the writable icon will always be plain text, and the exported data can only be the same, so management of the clipboard can and will be delegated to the Clipboard (and as a consequence of this, a Message_ClaimEntity 4 will be issued by the Clipboard every time data is cut or copied to the clipboard from a writable icon, including those in menu structures). <p /> <h3>Paste</h3> <p /> <h4>Protocol</h4> <p /> A"Paste" menu option, if provided, must be placed as described in the Style Guide; the option <u>must</u> be shaded if there is no data on the clipboard suitable for pasting into the document, even though this may entail a slight delay before opening of the submenu while the application interrogates the current owner of the clipboard. <p /> <u>The keypresses Ctrl-V and Insert (Wimp key codes &016 and &1CD) are both equivalent to choosing "Paste" from the menu.</u> <p /> If there is a selection present in the window before the paste operation, it must be deleted before the paste takes place; swapping the clipboard contents and the selection would prevent the same data being pasted multiple times. The new data is inserted at the caret, or where the old selection was positioned, and the pasted data is automatically selected, so that the user can immediately cut it again, should it be so desired. <p /> <u>If the data pasted from the clipboard is of type text, any instances of ASCII &0A, &0D, or both codes adjacently in either order must be treated equally, as a single newline.</u> <p /> <h4>Clipboard Module</h4> <p /> The use, or not, of the Clipboard module to handle paste operations will not affect the paste user interface. <p /> <h4>Writable Icons</h4> <p /> Keypresses will be honoured as described in §4.3.1 - although individual icons don't and shouldn't have menus, so the description of performing pastes via a menu is inappropriate. Handling the protocol for obtaining the pasted data will be delegated to the Clipboard. <p /> Pasted data must be available in text (data type &FFF) form, or else the keypress will be ignored. Only text up to the first instance of ASCII &00, &0A or &0D, or the length of the spare space in the data buffer (plus the length of any selection), will be considered; if this string contains other control characters, or characters forbidden by the validation string, the operation will be faulted with a beep. In this case, no characters are inserted and any pre-existing selection is neither deselected nor deleted. <p /> <h3>Drag</h3> <p /> <h4>Protocol</h4> <p /> <h5>General</h5> <p /> <u>When the user starts a drag-and-drop drag (which will always be with the Select button, at least for text selections), the selection is not deselected.</u> When the drag ends, the new data is selected, <u>which means that, unless the drag was a move operation, or the destination is in the same window as the source, the old selection will subsequently be redrawn as a shaded selection.</u> <p /> If, during any drag operation, the Escape key is pressed, the drag must be aborted. <u>Any other keypresses during a drag must be ignored</u> (except of course for the status of the Shift key at the beginning of the drag, which is responsible for exchanging the meanings of copy and move operations). <p /> <h5><u>Pointers</u></h5> <p /> During a drag, the pointer shape is changed to the new standard alternative pointer shape ptr_drop; this must be used instead of the alternatives employed by DataPower, TechWriter and others. The new pointer shape will be added to the Wimp's RAM sprite pool by the Clipboard module, so that it is always available for tasks to use. <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic11.gif" alt="" align="middle" height=43 width=294 /> <p /> The new pointer retains the styling of the default pointer, plus the handed-ness of it, while implying a lifting operation consistent with the drop shadows added by the DragASprite and DragAnObject modules, and yet is not completely dissimilar to the existing third party pointers. <p /> The ptr_drop pointer must remain in use throughout the drag operation, with the sole exception of during an autoscroll, when the Wimp's autoscroll pointers are used in preference - see §4.4.1.5. <p /> <h5>Dragboxes</h5> <p /> Linked to the pointer position, there will be at all times during the drag either a representation of the (potential) drop position, or of the original data, <u>but not both</u>. Which is used depends on both the sending and (potentially-) receiving tasks, and on the type of data being dragged: if the receiving task understands at least one of the the data types, it will draw the drop position; if not, the sending task is responsible for the representation of the original data. <p /> The representation of the original data, when required, can take the form of either a rotating-dash Wimp box of the same size as the original selection, <u>or of a DragASprite or DragAnObject rendering. As ever, if the CMOS indicates as such, a dragbox must be used instead of a DragASprite or DragAnObject drag. If a selection consisting of multiple, non-contiguous objects is to be represented without using a dragbox, the Wimp sprite "package" must be used, to match the Filer's behaviour.</u> <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic13.gif" alt="" align="middle" height=70 width=90 /><img src="/images/risc_os_open/specifications/clipboard/Pic14.gif" alt="" align="middle" height=70 width=90 /> <p /> Whether a dragbox is to be used or not, the representation is (of course) updated automatically by the Wimp to follow the pointer. <u>The box, sprite or object must always keep the same position relative to the pointer's active point as the original bounding box did at the click that started the drag - except that in the special case of the "package" sprite, the sprite must always be centred over the pointer's active point.</u> <p /> <h5>Ghost Carets</h5> <p /> The representation of the drop position - known as the ghost caret - has two typical forms. When the pointer is over a primarily textual region, and the task understands at least one of the available data types, the ghost caret can be displayed as a grey I-beam, "snapped" to the nearest character boundary. When the pointer is over a layout-based region, a grey bounding box, scaled according to the zoom setting of the window, can be displayed, snapped to any grid, guidelines, frame boundaries etc. as appropriate. <u>The two are not necessarily mutually exclusive; a DTP package might, for example, want to display an I-beam when underneath a text drag, but a scaled bounding box when underneath a sprite drag.</u> If neither form is appropriate, and the application knows of no other appropriate rendering either, the sending task must be informed (or be allowed to continue) to display the dragbox, sprite or whatever. <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic12.gif" alt="" align="middle" height=70 width=90 /><img src="/images/risc_os_open/specifications/clipboard/Pic15.gif" alt="" align="middle" height=70 width=90 /> <p /> While the task that technically owns the drag continues to be the sending task, the receiving task is responsible for drawing any ghost caret. Therefore the ghost caret position is only updated at each pass through the underlying message protocol, approximately four times a second. In order to prevent the sending task's dragbox or sprite from coexisting with the ghost caret, and thus cluttering the target area to an unnecessary extent, provision is made in the protocol for the receiving task to request that the drag be <u>replaced with a "drag point" (type 7) drag</u> for as long as the receiving task is displaying a ghost caret. <p /> <u>In textual documents, if during the drag, the pointer is positioned over the original selection, the ghost caret must not be displayed - the dragbox must be displayed instead. This is because dragging text inside itself has no meaning.</u> <p /> <h5>Scrolling</h5> <p /> During a drag, when the pointer is over a window that can scroll, autoscrolling must be turned on <u>using the SWI Wimp_AutoScroll. For more details of the effect of this SWI, see [5], but note that unless the pointer is held still near the edge of the window for a period, no scrolling will occur. Since determination of the pause zone is dependent upon positioning of panes etc., the activation and deactivation of Wimp_AutoScroll is the responsibility of the receiving task.</u> <p /> <h4>Clipboard Module</h4> <p /> The use, or not, of the Clipboard module to handle drag operations will not affect the drag user interface. <p /> <h4>Writable Icons</h4> <p /> Drags from writable icons will use the ptr_drop pointer, and a rotating-dash dragbox matched in size to the selection. If the pointer has not moved since the click, the drag will initially look like this (with the dashes rotating): <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic16.gif" alt="" align="middle" height=93 width=220 /> <p /> Drags to writable icons (including drags within the same icon) will use an I-beam ghost caret. The ghost-caret drawing facility of the Wimp will also be made available to applications, in order to ensure that all I-beam ghost carets are drawn to the same colour and design. The colour used will be the ColourTransed version of palette entry &80808000 (50.2% grey) in order to attain maximum contrast when EORed over every possible colour. <p /> If the pointer is dragged over the autoscrolling zone (as defined in §4.1.3.2), the icon will be scrolled in order to let the ghost caret be positioned in an out-of-sight part of the icon. This will happen even if the selection fills the icon (meaning that the ghost caret cannot be positioned anywhere in the icon) because there would be no visual clues as to why the autoscrolling was not occurring in this case. <p /> Window autoscrolling will not be initiated while the pointer is being dragged over a writable icon. However, if autoscrolling of the icon's window is already in progress and the pointer moves on to a writable icon, the ghost caret will not be placed in the writable icon. <p /> <h3>Drop</h3> <p /> <h4>Protocol</h4> <p /> <h5>Sending</h5> <p /> When a drag-and-drop drag ends, the sending task attempts to transfer data to the task under the pointer, or if a drag-and-drop dialogue was in effect, to the receiving task (which can only be different from the task under the pointer if the receiving task is autoscrolling one of its windows). The data type actually transferred is negotiated between the sending and receiving tasks at the time of the drop; it may entail either or both tasks performing data translation. <p /> The decision whether to delete the original data when the drag ends (i.e. whether to copy or move the selection) is based upon the state of the Shift key <u>when the drag began</u>, and upon whether the pointer position at the end of the drag is in the same <u>window</u> as at the start, or not. Drags within a <u>window</u> move the data unless Shift is held down; drags between <u>windows</u> copy the data unless Shift is held down. Shift reverses the meaning of the drag, so within a <u>region</u>, the selection is copied, and between <u>regions</u>, the selection is moved. <p /> The destination task can also insist that the operation be a move irrespective of the above; this is to allow for trashcan applications. <u>Drags to non-drag-and-drop applications (including the Filer) are treated the same as drags to a different window.</u> <p /> <u>In some circumstances, such as dropping data onto a directory viewer, the filename used in the data transfer protocols will become visible to the user. For these to be meaningful to the user, these filenames should follow the convention of concatenating the source of the data with the textual filetype, for example "IconText" or "PaintSprite".</u> <p /> <u>When generating data of type text that includes newline characters, you must use ASCII &0A to terminate lines.</u> <p /> <h5>Receiving</h5> <p /> To the destination task, a drop will appear the same as a non-drag-and-drop DataSave (inter-application data transfer) operation, except that the Wimp message is subtly marked (by virtue of having a non-zero your_ref field) as having resulted from previous messaging (i.e. the drag-and-drop dialogue). Assuming the task doesn't reject the data as being unsuitable, this is sufficient for the task to know what to do with the data: <p /> If a drag-and-drop drop, <ul> <li>If a ghost caret was being displayed, the insertion point is set to the last known ghost caret position.</li> <li>Otherwise, the insertion point is set to the position specified in the message (i.e. the pointer position), snapped if necessary.</li> </ul> <p /> <u>If a non-drag-and-drop drop,</u> <ul> <li><u>If a caret (shadow or not) or selection (shaded or not) is being displayed, the insertion point is set there.</u></li> <li><u>Otherwise, the insertion point is set to the position specified in the message, snapped if necessary.</u></li> </ul> <p /> <u>If the insertion point thus determined lies on a selection (shaded or not), the said selection must be cut to the clipboard. (This is the only circumstance in which the clipboard is affected by a drag-and-drop operation.)</u> The new data is inserted, and is then selected itself. <p /> <u>If the insertion point lies on the source selection, no actions must be taken. The selection remains selected.</u> <p /> <u>Received text data must be correctly handled whether newlines (if any) are indicated using ASCII &0A, &0D, or both characters in either order.</u> <p /> <h4>Clipboard Module</h4> <p /> The use, or not, of the Clipboard module to handle drop operations will not affect the drop user interface. <p /> <h4>Writable Icons</h4> <p /> The requirements for acceptance of dropped data are the same as for pasted data (see §4.3.3). <p /> Text dragged from a writable icon is not terminated in any way - the "file" length determines the amount of text. The leafname used for icon-sourced text will be "IconText"; because the data transfer message handling will be delegated to the Clipboard, there will be no opportunity to change the leafname so as not to overwrite an existing file of the same name. <p /> <h2>Programming Interface and Data Interchange</h2> <p /> These two sections have been combined because any programming interfaces being specified are intimately connected to data interchange, and it makes no sense to discuss the programming interfaces before the data interchange they relate to. <p /> <h3>Selection</h3> <p /> <h4>Protocol</h4> <p /> Handling mouse and key events relating to and rendering of selections is the responsibility of the task. The task may use Wimp_SetCaretPosition to delegate drawing of the caret, but non-I-beam carets and selections need to be drawn during window update and redraw code. To give a window the input focus without displaying the Wimp caret (for example, when setting a selection), Wimp_SetCaretPosition must be called with R4 bit 25 set. <p /> Whenever a cut-and-paste / drag-and-drop task gains either the caret or the selection, it must broadcast the following event 17 Wimp message with both flag bits 0 and 1 set: <p /> <table cellpadding=5> <tr><td colspan=6><b>Message_ClaimEntity (&0000F)</b> <tr><td> <td colspan=5>This message is broadcast by a task claiming the cut-and-paste / drag-and-drop caret, selection or clipboard. <tr><td> <td>R1+12 <td colspan=4>your_ref: 0 <tr><td> <td>R1+20 <td>flags: <td>bit 0/1 set <td>=> <td>caret or selection being claimed <tr><td> <td> <td> <td>bit 2 set <td>=> <td>clipboard being claimed (see §5.2.1) <tr><td> <td> <td> <td colspan=3>all other bits are reserved and must be clear </table> <p /> A task must determine if it is gaining, or merely repositioning the caret/selection by whether any other task has broadcast a Message_ClaimEntity with bits 0 or 1 set, since the last time the task in question broadcast such a message. Note in particular, this means that a task must not consider the caret to have been lost when the Wimp caret is grabbed by a non- cut-and-paste / drag-and-drop task. <p /> When a task receives Message_ClaimEntity with either one or both of bits 0 and 1 set, it must act as though both the caret and selection have been claimed - and therefore redraw any selection as a shaded selection, and either redraw the caret as a shadow caret, or remove the caret entirely (the latter will be done automatically if the task was using a Wimp-drawn user caret). <p /> Note that the Wimp does not issue this message when positioning either the caret or a selection within a menu structure. <p /> <h4>Clipboard Module</h4> <p /> The Clipboard is not involved in the selection process. However, any programs planning to rely entirely on the Clipboard to manage its cut-and-paste / drag-and-drop data transfer must still claim the caret and selection as described in §5.1.1. <p /> <h4>Writable Icons</h4> <p /> <h5>Wimp_SetCaretPosition API</h5> <p /> Wimp_SetCaretPosition will be extended to allow the following entities to be created: <ul> <li>Carets in writable icons that are not necessarily centred when the text is wider than the icon.</li> <li>"User" ghost carets - i.e. ghost carets not in an icon. *</li> <li>Ghost carets in writable icons (not necessarily centred). (See §5.4.3.)</li> <li>Selections in writable icons, centred when the text is wider than the icon. *</li> <li>Selections in writable icons, not necessarily centred when the text is wider than the icon.</li> </ul> <p /> Those entities above marked with an asterisk will also be made available to tasks. Any calls using the API for the others will be ignored, unless called using the internal Wimp routine. Below is the complete new Wimp_SetCaretPosition API, including the existing functionality, in a more digestible form than in the RISC OS 3 PRM. This includes the calls for internal use only; although these are internally distinguished by flags bit 28 being set, as far as the outside world is concerned, both bits 28 and 29 remain "reserved, must be zero". <p /> <table cellpadding=5> <tr><td colspan=5><b>Wimp_SetCaretPosition (SWI &400D2)</b> <tr><td> <td colspan=4>Set up the data for a new caret, ghost caret or selection position, and redraw it there. <tr><td colspan=5> On entry <tr><td> <td colspan=4>To remove the caret / ghost caret / selection: <tr><td> <td>R0 = <td colspan=3>-1 <tr><td> <td>R2 = <td>"TASK" => <td colspan=2>use bits 30 and 31 of R4 to determine which entity to remove, otherwise remove the caret <tr><td> <td>R3 = <td>flags <td colspan=2>bits other than 30 and 31 reserved, must be zero <tr><td> <td colspan=4><br /> To set a user caret / user ghost caret: <tr><td> <td>R0 = <td colspan=3>window handle <tr><td> <td>R1 = <td colspan=3>-1 <tr><td> <td>R2 = <td colspan=3>x-offset of caret / ghost caret, relative to work area origin <tr><td> <td>R3 = <td colspan=3>y-offset of caret / ghost caret, relative to work area origin <tr><td> <td>R4 = <td colspan=3>height of caret, and flags <tr><td> <td colspan=4><br /> To set an icon caret, centred if possible, by known index into the string: <tr><td> <td>R0 = <td colspan=3>window handle <tr><td> <td>R1 = <td colspan=3>icon handle <tr><td> <td>R4 = <td colspan=3>-1 <tr><td> <td>R5 = <td colspan=3>index of caret into string (must be >= 0) <tr><td> <td colspan=4>or alternatively, if you wish to override the default Y position, size or flags: <tr><td> <td>R0 = <td colspan=3>window handle <tr><td> <td>R1 = <td colspan=3>icon handle <tr><td> <td>R3 = <td colspan=3>y-offset of caret, relative to work area origin <tr><td> <td>R4 = <td colspan=3>height of caret, and flags (bits 28-31 all clear) <tr><td> <td>R5 = <td colspan=3>index of caret into string (must be >= 0) <tr><td> <td colspan=4><br /> To set an icon caret, centred if possible, by approximate current position on screen (note that if positioning the caret there causes the icon to scroll, the final caret position may be very different to the specified position): <tr><td> <td>R0 = <td colspan=3>window handle <tr><td> <td>R1 = <td colspan=3>icon handle <tr><td> <td>R2 = <td colspan=3>current x-offset of desired position, relative to work area origin <tr><td> <td>R3 = <td colspan=3>current y-offset of desired position, relative to work area origin <tr><td> <td>R5 = <td colspan=3>-1 <tr><td> <td colspan=4><br /> To set an icon caret / icon ghost caret, not necessarily centred: * <tr><td> <td>R0 = <td colspan=3>window handle <tr><td> <td>R1 = <td colspan=3>icon handle <tr><td> <td>R2 = <td colspan=3>new value of caret scrollx <tr><td> <td>R3 = <td colspan=3>0 (reserved for future expansion) <tr><td> <td>R4 = <td colspan=3>height of caret, and flags (bit 28 set, bit 30 set for ghost caret or clear for caret, bit 31 clear) <tr><td> <td>R5 = <td colspan=3>index of caret into string (must be >= 0) <tr><td> <td colspan=4><br /> To set an icon selection, centred if possible (or if the selection is wider than the icon, right-aligned within the icon): <tr><td> <td>R0 = <td colspan=3>window handle <tr><td> <td>R1 = <td colspan=3>icon handle <tr><td> <td>R4 = <td colspan=3>flags (bit 28 clear, bit 30 clear, bit 31 set) <tr><td> <td>R5 = <td colspan=3>index of lower boundary into string <tr><td> <td>R6 = <td colspan=3>index of upper boundary into string (no action is taken if R5 >= R6) <tr><td> <td colspan=4><br /> To set an icon selection, not necessarily centred: * <tr><td> <td>R0 = <td colspan=3>window handle <tr><td> <td>R1 = <td colspan=3>icon handle <tr><td> <td>R2 = <td colspan=3>new value of selection scrollx <tr><td> <td>R3 = <td colspan=3>0 (reserved for future expansion) <tr><td> <td>R4 = <td colspan=3>flags (bit 28 set, bit 30 clear, bit 31 set) <tr><td> <td>R5 = <td colspan=3>index of lower boundary into string <tr><td> <td>R6 = <td colspan=3>index of upper boundary into string (no action is taken if R5 >= R6) <tr><td> <td colspan=4><br /> Flag bits 30/31 determine which entity the call refers to, and also affect the other flag bit meanings: <tr><td> <td>Value <td>Entity <td>Bit(s) <td>Meaning (if one bit, then meaning when set) <tr><td> <td> 0 <td>Caret <td>0-15 <td>height in OS units (0-65535) <tr><td> <td> <td> <td>16-23 <td>colour (bits 20-23 ignored if a Wimp colour number) <tr><td> <td> <td> <td>24 <td>use a Wimp-drawn caret rather than the Font Manager caret <tr><td> <td> <td> <td>25 <td>do not draw the I-beam (caret is invisible) <tr><td> <td> <td> <td>26 <td>use bits 16-23 for colour (else defaults to colour 11) <tr><td> <td> <td> <td>27 <td>colour is a GCOL, otherwise a Wimp colour number <tr><td> <td> <td> <td>28 <td>use both R2 and R5 to position the caret in an icon and override centring behaviour (internal use only, must be zero for external callers) <tr><td> <td> <td> <td>29 <td>reserved, must be zero <tr><td> <td> 1 <td>Ghost caret <td>0-15 <td>height in OS units (0-65535) <tr><td> <td> <td> <td>16-23 <td>not used; must be zero (palette entry &80808000 always used) <tr><td> <td> <td> <td>24 <td>use a Wimp-drawn caret rather than the Font Manager caret <tr><td> <td> <td> <td>25-27 <td>not used; must be zero (cannot be invisible, colour is fixed) <tr><td> <td> <td> <td>28 <td>use both R2 and R5 to position the ghost caret in an icon and override centring behaviour (internal use only, must be zero for external callers) <tr><td> <td> <td> <td>29 <td>reserved, must be zero <tr><td> <td> 2 <td>Selection <td>0-25 <td>not used; must be zero (height and colour determined by icon properties and bit 26) <tr><td> <td> <td> <td>26 <td>use shaded selection colour scheme (also implies that the window containing the selection should not be awarded the input focus as the result of this call) <tr><td> <td> <td> <td>27 <td>the window containing the selection should not be awarded the input focus, even if it is not shaded <tr><td> <td> <td> <td>28 <td>use both R2 and R5/R6 to position the selection in an icon and override centring behaviour (internal use only, must be zero for external callers) <tr><td> <td> <td> <td>29 <td>reserved, must be zero <tr><td> <td> 3 <td>Reserved <td> <td> <tr><td colspan=5> On exit <tr><td> <td colspan=4>R0-R5 are preserved, except that if R0 was -1 and R2 was "TASK" on entry, then R2 is set to zero on exit. <tr><td> <td colspan=4>The versions of the indexes into the string held internally, after an icon caret is positioned by index, will in future be restricted to the range { 0 <= index <= length } rather than just { index >= 0 }. This is essentially a bugfix, and will affect the values returned by Wimp_GetCaretPosition. </table> <p /> <h5>Wimp_GetCaretPosition API</h5> <p /> The complimentary SWI will be extended to allow for Wimp_SetCaretPosition's new functionality: <table cellpadding=5> <tr><td colspan=4><b>Wimp_GetCaretPosition (SWI &400D3)</b> <tr><td> <td colspan=3>Returns details of the state of the caret, ghost caret or writable icon selection. <tr><td colspan=4> On entry <tr><td> <td>R0 = <td colspan=2>if R2 = "TASK", this is the entity to inspect (0 => caret, 1 => ghost caret, 2 => selection) <tr><td> <td>R1 -> <td colspan=2>block to fill with entity state <tr><td> <td>R2 = <td>"TASK" => <td>fill block with state of entity specified by R0 and R3, else fill block with caret state <tr><td> <td>R3 = <td colspan=2>if R0 = 2 and R2 = "TASK", this is either the handle of the window to inspect, or -1 to inspect the window which currently has the input focus and therefore also the only un-shaded selection <tr><td colspan=4> On exit <tr><td> <td>R0 <td>corrupted <td> <tr><td> <td>R1 <td>preserved <td> <tr><td> <td>R2 = <td colspan=2>0 if it was "TASK" on entry <td> <tr><td> <td>R3 <td>preserved <tr><td> <td colspan=3><br /> If the caret or ghost caret state is being returned, the block is filled as follows: <tr><td> <td>R1+0 <td colspan=2>window handle (or -1 if there is no [ghost] caret) <tr><td> <td>R1+4 <td colspan=2>icon handle (or -1 if a user [ghost] caret) <tr><td> <td>R1+8 <td colspan=2>x-offset of [ghost] caret, relative to work area origin <tr><td> <td>R1+12 <td colspan=2>y-offset of [ghost] caret, relative to work area origin <tr><td> <td>R1+16 <td colspan=2>height of [ghost] caret and flags (bit 28 clear) <tr><td> <td>R1+20 <td colspan=2>index of [ghost] caret into string (undefined if a user [ghost] caret) <tr><td> <td colspan=3><br /> If the selection state is being returned, the block is filled as follows: <tr><td> <td>R1+0 <td colspan=2>window handle (or -1 if there is no writable icon selection) <tr><td> <td>R1+4 <td colspan=2>icon handle (>= 0) <tr><td> <td>R1+8 <td colspan=2>x-offset of lower boundary of selection, relative to work area origin <tr><td> <td>R1+12 <td colspan=2>width of selection <tr><td> <td>R1+16 <td colspan=2>y-offset of selection, relative to work area origin <tr><td> <td>R1+20 <td colspan=2>height of selection and flags (bit 28 clear) <tr><td> <td>R1+24 <td colspan=2>index of lower boundary into string <tr><td> <td>R1+28 <td colspan=2>index of upper boundary into string </table> <p /> <h3>Cut and Copy</h3> <p /> <h4>Protocol</h4> <p /> When a cut or copy operation is requested of an application, it must copy the selected data to the clipboard. Under the raw protocol, each task is responsible for allocating (and deallocating) the memory necessary to store the clipboard. <u>The clipboard must hold the data in a form from which it can be translated to the maximum number of other data types, which usually means it must be held in the application's internal format.</u> <p /> In order to ensure that only one clipboard is active globally at a time, it is necessary that when a cut or copy operation is performed, the cutting/copying task broadcasts a Message_ClaimEntity (see §5.1.1) with bit 2 set. Accordingly, when a task receives such a message, it must deallocate the memory used to store its own clipboard (unless of course, its own clipboard was not in use). The message must not be sent if the same task already owned the clipboard. <p /> <h4>Clipboard Module</h4> <p /> One of the Clipboard's functions is to allocate and manage memory to store the clipboard data for any participating tasks, following a cut or copy operation. <p /> However, the Clipboard has no intrinsic knowledge of how to translate data between different formats, so it is essential that no task uses the Clipboard for this purpose if it is able to translate data on export. For example, none of Edit, Paint or Draw can exclusively use the Clipboard for clipboard storage - Edit could export Basic programs as a tokenised file, or as text; Paint can export both sprites and palettes; and Draw can export text, sprites, JPEGs and PostScript as well as DrawFiles. <p /> Despite this, the raw protocol messaging involved at the pasting stage is still not completely trivial, and so an alternative method will be provided, whereby the task is still responsible for storing the clipboard and translating the data when required, but the Clipboard handles all the associated Wimp messaging. This also allows some code sharing with the data-send end of the drop operation. <p /> <table cellpadding=5> <tr><td colspan=6><b>SWI Clipboard_Put (&4E000)</b> <tr><td> <td colspan=5>Puts data on the clipboard, or initiates the data-send of a drop (see §5.4.2). <tr><td colspan=6>On entry <tr><td> <td>R0 = <td>flags: <td>bit 0 set <td>=> <td>clear the clipboard (must be used when the application exits, unless another task has since claimed the clipboard using a Message_ClaimEntity 4) <tr><td> <td> <td> <td>bit 1 set <td>=> <td>do not store the data, just the data length (and the task handle) - when the data is required, the Clipboard will send the clipboard-owning task a Message_PutRequest stating the required data type, see §5.3.2 <tr><td> <td> <td> <td>bit 2 set <td>=> <td>R1 is a pointer to a data type list, otherwise R1 is the data type <tr><td> <td> <td> <td>bit 31 set <td>=> <td>flag reply messages as for the attention of the Wimp <tr><td> <td> <td> <td colspan=3>all others are reserved and must be zero <tr><td> <td>R1 = <td colspan=4>depending on flags bit 2, either the data type (in bits 0-11), or a pointer to non-null list of data types that the task can translate the data to (in no particular order), terminated by -1 <tr><td> <td>R2 = <td colspan=4>pointer to data (if flags bit 1 is clear) <tr><td> <td>R3 = <td colspan=4>data length <tr><td> <td>R4 = <td colspan=4>pointer to proposed leafname of data, null-terminated <tr><td> <td>R5 = <td colspan=4>my_ref of Message_PutRequest which this is a reply to, or 0 if this isn't a reply <tr><td colspan=6>On exit <tr><td> <td colspan=5>R0-R5 preserved <tr><td> <td colspan=5>The Clipboard broadcasts a Message_ClaimEntity 4 (unless the Clipboard owns the clipboard already), and takes a copy of the data, the leafname and the data type list, as appropriate. An error is generated if any of the pointers are invalid. </table> <p /> This SWI can be used for three main purposes: <OL> <li>passing clipboard data to the Clipboard module to handle on the application's behalf</li> <li>passing enough information about the clipboard to the Clipboard so it can advertise on our behalf (or <i>proxy</i>) and get back to the application if and when a paste operation happens</li> <li>passing selection data to the Clipboard</li> </OL> <p /> The first and second cases can be initiated by the application, often in response to a Ctrl-C or Ctrl-X keypress. In this case, R5 will be 0. The first and third cases should be called in response to a Message_PutRequest, which is sent to the application by the Clipboard module if it called SWI Clipboard_Put (second case) or SWI Clipboard_StartDrag respectively, and a paste or drop operation (respectively) has been performed by the user. <p /> Deleting the data in the main document following a cut operation remains the task's responsibility. If a task is maintaining its own clipboard storage area, it must release the memory when it receives a Message_ClaimEntity 4 broadcast. When a task exits, if it is maintaining the clipboard, or if Clipboard is maintaining the clipboard for it, the task must call Clipboard_Put with flags bit 0 set, for consistency with applications that do everything themselves. <p /> <h4>Writable Icons</h4> <p /> The Wimp itself is not a Wimp task. One of the consequences of this is that it has no task handle, and is as such not well suited to handling Wimp messages. Because of this, it will make heavy use of the Clipboard. <p /> When the user types Ctrl-C or Ctrl-X in a writable icon, the Wimp will call Clipboard_Put with all flags clear and a data type of &FFF. The data will not be terminated; only the data length word will determine the extent of the data. <p /> <h3>Paste</h3> <p /> <h4>Protocol</h4> <p /> The application must first check to see if it owns the clipboard, and use the data directly if so. If it does not own it, it must broadcast a Message_DataRequest <u>(message type 18)</u>: <p /> <table cellpadding=5> <tr><td colspan=6><b>Message_DataRequest (&00010)</b> <tr><td> <td colspan=5>This message is broadcast by a task when it wishes to paste data from a clipboard maintained by another task. <tr><td> <td>R1+12 <td colspan=4>your_ref: 0 <tr><td> <td>R1+20 <td colspan=4>destination window handle <tr><td> <td>R1+24 <td colspan=4>internal handle to indicate destination of data; <u>may be icon handle (see below)</u> <tr><td> <td>R1+28 <td colspan=4>destination x co-ordinate <tr><td> <td>R1+32 <td colspan=4>destination y co-ordinate <tr><td> <td>R1+36 <td>flags: <td>bit 2 set <td>=> <td>send data from clipboard <tr><td> <td> <td> <td colspan=3>all other bits are reserved and must be clear <tr><td> <td>R1+40 <td colspan=4>list of data types in receiver's order of preference, terminated by -1 <u>(may be null)</u> </table> <p /> Flags bit 2 must be set when the message is sent. If the message is received with flags bit 2 clear, the message must be ignored. <p /> If an application receiving the message owns the clipboard, it must choose the earliest data type in the list that it can provide, and if none are possible <u>(or the list is null)</u> it must provide the data in its original (native) format. It must reply using the normal Message_DataSave protocol. Bytes 20-35 of the DataSave block must be copied directly from the corresponding bytes of the Message_DataRequest block (despite the discrepancy between icon handle and internal handle), while the estimated size, data type and leafname must be filled appropriately. <u>The your_ref of the Message_DataSave must be the my_ref of the Message_DataRequest.</u> <p /> <u>Be aware that if the Wimp sees an incoming DataSave with a valid icon handle at bytes 24-27 (i.e. less than the number of icons created in the windows), it will assume that it is a request to paste into that icon. Consequently, an application must be careful how it allocates its internal handles for use in this message. For example, it could use pointers into application space, which will be above &8000 and therefore very unlikely to clash with an icon handle.</u> <p /> When the task that initiated the paste receives the Message_DataSave, it must check the data type to ensure that it knows how to deal with it - it may be the clipboard owner's native format. If it cannot, it may back out of the transaction by ignoring the message. Otherwise, it must continue with the conventional DataSave protocol, preferably using memory data transfer. <p /> If an application needs to find out whether there is data available to paste, but does not actually want to receive the data (e.g. in order to determine whether a "Paste" menu option should be shaded), it must broadcast a Message_DataRequest as described above. If no task replies (i.e. the message bounces) then there is no clipboard data available. If a Message_DataSave is received, then the application must ignore it (i.e. fail to reply), which will cause the operation to be silently aborted by the other task. The data type field of the Message_DataSave can then be used to determine whether the data being offered by the other task is in a suitable format to be pasted. <p /> <h4>Clipboard Module</h4> <p /> <h5>The Complete Paste Process</h5> <p /> During the paste process, the Clipboard behaves to conventional drag-and-drop tasks exactly like any other clipboard owner, and responds to Message_DataRequests as described above. <p /> It also provides an alternative interface to the pasting process, involving much less messaging. It involves SWI Clipboard_Get and the messages Message_PutRequest and Message_Paste. However, as before, if a task is managing its own clipboard, it must use the data directly in preference (although this will now only be in cases where the data can be translated on export). <p /> <table cellpadding=5> <tr><td colspan=6><b>SWI Clipboard_Get (&4E001)</b> <tr><td> <td colspan=5>Requests data from the clipboard, using the Clipboard as a proxy. <tr><td colspan=6>On entry <tr><td> <td>R0 = <td>flags: <td>bit 31 set <td>=> <td>flag reply messages as for the attention of the Wimp (this bit must only be set by the Wimp) <tr><td> <td> <td> <td colspan=3>all others are reserved and must be clear <tr><td> <td>R1 = <td colspan=4>destination window handle <tr><td> <td>R2 = <td colspan=4>destination icon handle (-1 if none) <tr><td> <td>R3 = <td colspan=4>destination x co-ordinate <tr><td> <td>R4 = <td colspan=4>destination y co-ordinate <tr><td> <td>R5 = <td colspan=4>pointer to list of data types that the task is interested in receiving, in order of preference, terminated by -1 (may be a null list if the native format is required) <tr><td colspan=6>On exit <tr><td> <td colspan=5>R0-R5 preserved <tr><td> <td colspan=5>The Clipboard takes an internal copy of the data type list. If it owns the clipboard itself, it replies immediately with a Message_Paste. If a task has registered itself with the Clipboard using a bit-1-set SWI Clipboard_Put, the Clipboard sends a Message_PutRequest to the clipboard owner, and uses the data copied from the details in the following SWI Clipboard_Put to construct a Message_Paste. Alternatively, if a conventional drag-and-drop task owns the clipboard, the Clipboard will send a Message_DataRequest and handle all the Message_DataSave etc. messaging, before sending a Message_Paste to the pasting task, thus creating a uniform interface. </table> <p /> <table cellpadding=5> <tr><td colspan=6><b>Message_PutRequest (&4E000)</b> <tr><td> <td colspan=5>This message requests that clipboard or selection data be sent to the Clipboard. <tr><td> <td>R1+12 <td colspan=4>your_ref: 0 <tr><td> <td>R1+20 <td>flags: <td>bit 0 <td>=> <td>flags bit 0 to use in Clipboard_Put <tr><td> <td> <td> <td>bit 1 <td>=> <td>flags bit 1 to use in Clipboard_Put <tr><td> <td> <td> <td>bit 2 <td>=> <td>flags bit 2 to use in Clipboard_Put (note this also determines whether a single data type, or a data type list pointer is required in R3) <tr><td> <td> <td> <td>bit 3 set <td>=> <td>send the clipboard (otherwise send the selection) <tr><td> <td> <td> <td>bit 4 set <td>=> <td>delete the selection after sending the data <tr><td> <td> <td> <td>bit 31 set <td>=> <td>message is for the attention of the Wimp, other tasks must ignore it <tr><td> <td> <td> <td colspan=3>all others are reserved and must be clear <tr><td> <td>R1+24 <td colspan=4>destination window handle <tr><td> <td>R1+28 <td colspan=4>destination icon handle (-1 if none) <tr><td> <td>R1+32 <td colspan=4>destination x co-ordinate <tr><td> <td>R1+36 <td colspan=4>destination y co-ordinate <tr><td> <td>R1+40 <td colspan=4>pointer to list of data types that the destination task is interested in receiving, in order of preference, terminated by -1 (may be a null list if the native format is required) - now held in the Clipboard's workspace </table> <p /> Message_PutRequest is sent exclusively by the Clipboard. Any task receiving the message must reply before the next Wimp_Poll using SWI Clipboard_Put with, preserving flags bit 0-2 and 31. <p /> The message is used both for providing the data in a paste operation (when data translation has to be delayed until paste-time) and in a drop operation, so care must be taken to send the data from either the internal clipboard or the selection, respectively. Bit 4 caters for move-drags (see §5.4.2). <p /> The data type chosen must be the first one in the list that it can provide, or the native data type if none (or if the list is null). The data must be translated prior to calling Clipboard_Put (unless bit 2 is set), as it is at that stage that the Clipboard takes an internal copy of the data. The leafname must be built as described in §4.5.1.1. <p /> <table cellpadding=5> <tr><td colspan=6><b>Message_Paste (&4E001)</b> <tr><td> <td colspan=5>This message informs the task being pasted to or dropped upon that the data is ready to be received. <tr><td> <td>R1+12 <td colspan=4>your_ref: 0 <tr><td> <td>R1+20 <td>flags: <td>bit 0 set <td>=> <td>Clipboard couldn't find any clipboard after a Clipboard_Get call - take no further action <tr><td> <td> <td> <td>bit 31 set <td>=> <td>message is for the attention of the Wimp, other tasks must ignore it <tr><td> <td> <td> <td colspan=3>all others are reserved and must be clear <tr><td> <td>R1+24 <td colspan=4>destination window handle <tr><td> <td>R1+28 <td colspan=4>destination icon handle (-1 if none) or internal handle if initiated by a Message_DataRequest <tr><td> <td>R1+32 <td colspan=4>destination x co-ordinate <tr><td> <td>R1+36 <td colspan=4>destination y co-ordinate <tr><td> <td>R1+40 <td colspan=4>data type <tr><td> <td>R1+44 <td colspan=4>pointer to data, or 0 if flag bit 0 set <tr><td> <td>R1+48 <td colspan=4>data length <tr><td> <td>R1+52 <td colspan=4>pointer to proposed leafname of data, null-terminated, or 0 if flag bit 0 set </table> <p /> This message is also sent exclusively by the Clipboard. The data type must first be checked for suitability, then the data must be copied before the next Wimp_Poll, as the Clipboard will free up the memory unless it was itself the owner of the clipboard (the task must not attempt to determine whether this is the case). <p /> Note that the Clipboard stores data in its own application slot, and this is where the pointer at R1+44 lies, so in order to copy the data, you must use Wimp_TransferBlock. The Clipboard's task handle (required by Wimp_TransferBlock) may be obtained from R1+4. <p /> <h5>Interactions</h5> <p /> The five possible interactions during a paste operation are outlined below. The solid lines refer to the complete paste process, and the dotted lines refer to clipboard data type determination, as described in §5.3.2.3. Lines are diagonal where a task switch is performed (i.e. for the sending of messages rather than the use of SWIs). Note that the "clipboard-owning task" is the task that most recently performed a cut or copy operation - strictly speaking, if the task is cooperating with the Clipboard, the Clipboard is the clipboard owner. <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic17.gif" alt="" align="middle" height=126 width=520 /><br /> <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic18.gif" alt="" align="middle" height=154 width=520 /><br /> <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic19.gif" alt="" align="middle" height=309 width=520 /><br /> <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic20.gif" alt="" align="middle" height=253 width=520 /><br /> <P align="center"> <img src="/images/risc_os_open/specifications/clipboard/Pic21.gif" alt="" align="middle" height=253 width=520 /> <p /> In the fifth case, it is necessary for the Clipboard to ack the Message_DataRequest so that it doesn't bounce while the Message_PutRequest is delivered to the clipboard-owning task. <p /> <h5>Clipboard Data Type Determination</h5> <p /> Since the Clipboard is responsible for performing the traditional data transfer protocol, tasks that use the Clipboard need another way in which to determine whether they can use the current clipboard data. This will be provided by the Clipboard using the SWI Clipboard_GetDataType and the message Message_DataTypeIs. <p /> <table cellpadding=5> <tr><td colspan=6><b>SWI Clipboard_GetDataType (&4E002)</b> <tr><td> <td colspan=5>Requests data type of the clipboard, using the Clipboard as a proxy. <tr><td colspan=6>On entry <tr><td> <td>R0 = <td>flags: <td>bit 31 set <td>=> <td>flag reply messages as for the attention of the Wimp (this bit must only be set by the Wimp, even though there are currently no plans for it to do so at present) <tr><td> <td> <td> <td colspan=3>all others are reserved and must be clear <tr><td> <td>R1 = <td colspan=4>destination window handle <tr><td> <td>R2 = <td colspan=4>destination icon handle (-1 if none) <tr><td> <td>R3 = <td colspan=4>destination x co-ordinate <tr><td> <td>R4 = <td colspan=4>destination y co-ordinate <tr><td> <td>R5 = <td colspan=4>pointer to list of data types that the task is interested in receiving, in order of preference, terminated by -1 (may be a null list if the native format is required) <tr><td colspan=6>On exit <tr><td> <td colspan=5>R0-R5 preserved <tr><td> <td colspan=5>The Clipboard takes an internal copy of the data type list. If it owns the clipboard itself, it replies immediately with a Message_DataTypeIs. If a task has registered itself with the Clipboard using a bit-1-set SWI Clipboard_Put, the Clipboard sends a Message_PutRequest to the clipboard owner, and uses the (single) data type returned in the following SWI Clipboard_Put to construct a Message_DataTypeIs. Alternatively, if a conventional drag-and-drop task owns the clipboard, the Clipboard will send a Message_DataRequest, but fail to reply to the subsequent Message_DataSave; the data type from the Message_DataSave is used in the Message_DataTypeIs, thus creating a uniform interface. </table> <p /> <table cellpadding=5> <tr><td colspan=6><b>Message_DataTypeIs (&4E002)</b> <tr><td> <td colspan=5>This message informs a task of the data type of the clipboard (subject to the data type list passed to the preceding SWI Clipboard_GetDataType). <tr><td> <td>R1+12 <td colspan=4>your_ref: 0 <tr><td> <td>R1+20 <td>flags: <td>bit 0 set <td>=> <td>Clipboard couldn't find any clipboard after a Clipboard_GetDataType call <tr><td> <td> <td> <td>bit 31 set <td>=> <td>message is for the attention of the Wimp, other tasks must ignore it <tr><td> <td> <td> <td colspan=3>all others are reserved and must be clear <tr><td> <td>R1+24 <td colspan=4>destination window handle <tr><td> <td>R1+28 <td colspan=4>destination icon handle (-1 if none) <tr><td> <td>R1+32 <td colspan=4>destination x co-ordinate <tr><td> <td>R1+36 <td colspan=4>destination y co-ordinate <tr><td> <td>R1+40 <td colspan=4>data type </table> <p /> <h4>Writable Icons</h4> <p /> The Wimp will use the Clipboard to obtain data when it needs to be pasted. It will (effectively) install a temporary post-poll filter on the task owning the icon, in order to detect the flags-bit-31-set Message_Paste that follows a Clipboard_Get SWI call. The message event will not be claimed, so that a task can be kept informed about what is being done to its icons - but the task must not change the contents of the icon, because the Wimp will already have done so. <p /> Since the Wimp will only export text from writable icons, and as such will have used the bit-1-clear version of Clipboard_Put, it will not have to respond to Message_PutRequests (except as a result of a drag-and-drop, see §5.4.2). <p /> The Wimp will not call Clipboard_GetDataType, so need not respond to Message_DataTypeIs. <p /> <h3>Drag and Drop</h3> <p /> <h4>Protocol</h4> <p /> During a traditional drag operation, no messaging takes place until the drop. However, during a drag-and-drop drag, a dialogue is set up between the dragging (sending) task and the potentially-receiving (claiming) task - which, in general, is the task owning the window under the pointer at any given time. <p /> <h5>Responsibilities</h5> <p /> The sending task's responsibilities include: <ul> <li>checking the status of the Shift key at the beginning of the drag</li> <li>setting the pointer shape to <u>ptr_drop</u> at the beginning of the drag, resetting the pointer shape to <u>ptr_drop</u> when the claiming task has finished with using an alternative pointer shape, <u>and setting it back to ptr_default at the end of the drag</u></li> <li>calling Wimp_DragBox, <u>DragASprite_Start/Stop or DragAnObject_Start/Stop,</u> as appropriate, at the beginning and end (abortion or completion) of the drag, and whenever the claiming task starts or stops requiring that the dragged object be removed from view (during such a period, a <u>type 7 Wimp_DragBox "dragpoint"</u> must be used instead)</li> <li>contacting the claiming task every 0.25 seconds, stating the screen position and "real life" bounding box of the data and the data types in which it is available</li> <li>initiating the drop when the drag ends</li> <li>deleting the selected data after a successful drop if (drag was within the same window AND Shift was not held down) OR (drag was between windows <u>or to a type-15 writable icon in any window</u> AND Shift was held down) OR the destination is a trashcan application</li> <li>aborting the drag (and informing the claiming task as such) when the user presses Escape (which means the sending task must retain the input focus throughout the drag)</li> </ul> <p /> The claiming task's responsibilities include: <ul> <li>updating the ghost caret according to the data passed from the sending task, provided at least one available data type can be used (and telling the sending task to remove the dragged object if a ghost caret is being displayed)</li> <li>automatically scrolling the window <u>if the pointer is paused near the edge of a document window (and changing the pointer to reflect as such at the beginning of the autoscroll - changing it back at the end is the sending task's responsibility)</u></li> <li>letting the sending task know its preferred ordering of data types, so that the sending task can work out which data type to send during the drop</li> <li>letting the sending task know if it the claiming task is a trashcan (i.e. that the source data must be deleted)</li> </ul> <p /> <u>A task must only claim the drag if it can do something useful with the handles and co-ordinates passed to it</u> - typically a response would be made when the pointer is over a text area or in the autoscrolling pause zone, but not when over a "dead" area like a page border, and not when over a writable icon (except that being over an autoscrolling pause zone takes precedence over being over a dead zone or icon). <p /> In practice, the claiming task can choose to continue to be involved in the dialogue, even when the pointer is no longer over one of its windows. This is to allow autoscrolling to continue, even when the pointer is dragged outside the window being autoscrolled (although this must not occur if the pointer has been moved smoothly over the window boundary without pausing over the window's autoscrolling activation zone). In fact, the default behaviour is for the dialogue to continue between the same two tasks, until the claiming task bows out by letting the sending task's message bounce. The claiming task, being the one handling the autoscrolling, is of course the one that knows best when this is necessary. <p /> <h5>Messaging</h5> <p /> The sending task sends a Message_Dragging, and the claiming task replies with a Message_DragClaim, as follow: <p /> <table cellpadding=5> <tr><td colspan=6><b>Message_Dragging (&00011)</b> <tr><td> <td colspan=5>This message is sent by a sending task to a (prospective) claiming task at intervals of 0.25 second, carrying context-sensitive information about the drag. <tr><td> <td>R1+12 <td colspan=4>your_ref: <u>my_ref of last Message_DragClaim (or 0 if there was no claimant last time, or if this is the first Message_Dragging)</u> <tr><td> <td>R1+20 <td colspan=4>destination window handle (constructed from Wimp_GetPointerInfo) <tr><td> <td>R1+24 <td colspan=4>destination icon handle (constructed from Wimp_GetPointerInfo) <tr><td> <td>R1+28 <td colspan=4>destination x co-ordinate (constructed from Wimp_GetPointerInfo) <tr><td> <td>R1+32 <td colspan=4>destination y co-ordinate (constructed from Wimp_GetPointerInfo) <tr><td> <td>R1+36 <td>flags: <td>bit 1 set <td>=> <td>sending data from selection <u>(for information only, receiver must ignore)</u> <tr><td> <td> <td> <td>bit 2 set <td>=> <td>sending data from clipboard -<u> i.e. from a clipboard-displaying window (for information only, receiver must ignore)</u> <tr><td> <td> <td> <td>bit 3 set <td>=> <td>source data will be deleted <u>(for information only, and unfortunately is incorrect when generated by DataPower; receiver must ignore)</u> <tr><td> <td> <td> <td>bit 4 set <td>=> <td><u>drag is being aborted</u>, do not respond to this message <tr><td> <td> <td> <td colspan=3>all other bits are reserved and must be clear <tr><td> <td>R1+40 <td colspan=4>xmin, ymin, xmax, ymax (4 bytes each): bounding box of data, relative to pointer, measured in millipoints (1/72000th of an inch), <i>not</i> scaled according to the zoom factor(s) of the source window; xmin > xmax means data has no bounding box, or bounding box is unknown <tr><td> <td>R1+56 <td colspan=4>list of available data types <u>in no particular order</u>, terminated by -1 <u>(must not be null)</u> </table> <p /> <table cellpadding=5> <tr><td colspan=6><b>Message_DragClaim (&00012)</b> <tr><td> <td colspan=5>This message is sent by a claiming task to the sending task in response to a Message_Dragging, carrying context-sensitive information about the drag. <u>It must only be issued if the claiming task is interested in at least one available data type.</u> <tr><td> <td>R1+12 <td colspan=4>your_ref: my_ref of last Message_Dragging <tr><td> <td>R1+20 <td>flags: <td>bit 0 set <td>=> <td>a pointer shape other than ptr_drop is in use <tr><td> <td> <td> <td>bit 1 set <td>=> <td>claiming task requires the absence of the Wimp dragbox / DragASprite sprite / DragAnObject object <tr><td> <td> <td> <td>bit 3 set <td>=> <td>claiming task is a trashcan application, so the source data must be deleted irrespective of Message_Dragging's flags bit 3 <u>(else deletion of the source data is determined by sending task)</u> <tr><td> <td> <td> <td colspan=3>all other bits are reserved and must be clear <tr><td> <td>R1+24 <td colspan=4>list of available data types in receiver's order of preference, terminated by -1 <u>(may be null)</u> </table> <p /> <u>Tasks are free to use internal routines to keep track of drags within or between windows that it owns, avoiding the performance overhead of all the messaging, as long as the user interface is indistinguishable from that which would result otherwise. Note in particular, that if the pointer is found to be over a type-15 writable icon, messaging must be turned back on as though the pointer was over a window owned by another task; this is so that the Wimp can collaborate in the dragging dialogue. Fortunately, the only application which currently uses this optimisation is Easi/TechWriter, where all the writable icons are in transient (or pseudo-transient) dialogue boxes, so this problem will never be visible, provided new implementations of drag-and-drop in applications follow these revised guidelines.</u> <p /> <h5>Use</h5> <p /> In event-driven terms, the sending and claiming tasks must follow the behaviour outlined below in order to implement every aspect of the protocol. Explanatory comments are italicised (and are all new in this specification). <p /> "Message type 17/18" means "use message type 17 unless drag_finished is 'true', when you must use message type 18". <i>This is an optimisation, because we're not interested if Message_Dragging bounces from a non-drag-and-drop task, until the end of the drag, when we will want to send the data by simple data transfer.</i> <p /> <b>Sending task:</b> <ul> <li>At <u>drag</u> start,</li> <ul> <li>enable null events every 0.25 seconds;</li> <li>call Wimp_DragBox <u>(with a drag type of 5), DragASprite_Start or DragAnObject_Start as appropriate (remember to use the dragbox if CMOS states that dragged sprites/objects must not be used);</u></li> <li><u>program pointer shape to ptr_drop;</u></li> <li><u>set shift_pressed to indicate current status of the Shift keys;</u></li> <li>set claimant to 'none' <i>(-1 is a suitable invalid task handle for this purpose)</i>;</li> <li>set drag_finished to 'false';</li> <li>set drag_aborted to 'false';</li> <li>set lastref to 'none' <i>(0 is suitable for this purpose)</i>.</li> </ul> <li>At drag abort (when Escape pressed during a drag),</li> <ul> <li><u>disable null events;</u></li> <li>call Wimp_DragBox -1, <u>DragASprite_Stop or DragAnObject_Stop as appropriate (or Wimp_DragBox -1 if old_dragclaim_flags has bit 1 set)</u>;</li> <li><u>program pointer shape to ptr_default;</u></li> <li>set drag_finished and drag_aborted to 'true';</li> <li>proceed as for a null event...</li> </ul> <li>At drag end (when User_Drag_Box event is received),</li> <ul> <li><u>disable null events;</u></li> <li><u>if necessary, call DragASprite_Stop or DragAnObject_Stop;</u></li> <li><u>program pointer shape to ptr_default;</u></li> <li>set drag_finished to 'true';</li> <li>proceed as for a null event...</li> </ul> <li>At null events,</li> <ul> <li>construct Message_Dragging using data from Wimp_GetPointerInfo and the value of drag_aborted;</li> <li>if claimant is 'none', send message type 17/18 to window owner with your_ref = 0;</li> <li>else, send message type 18 to claimant with your_ref = lastref.</li> </ul> <li>When Message_DragClaim is received,</li> <ul> <li>if drag_finished is 'true',</li> <ul> <li><i>drag has ended successfully while a claim is in force</i></li> <li>if drag_aborted is 'false' <i>(this comparison is not strictly necessary, since the claiming task is not supposed to reply when the drag is being aborted)</i>,</li> <ul> <li>initiate enhanced drop operation (send Message_DataSave to claimant, using first possible data type in the list, or the native data type if none are possible, and using your_ref = my_ref of the Message_DragClaim, then delete the source data if shift_pressed and the new window/icon handles (or the trashcan flag bit in Message_DragClaim) indicate as such.</li> </ul> </ul> <li>else,</li> <ul> <li><i>drag is continuing AND (a claim is in force, or a claim is starting)</i></li> <li><u>if lastref != 'none',</u></li> <ul> <li><i>claim is continuing, not just starting</i></li> <li>if old_dragclaim_flags bit 0 is set, but the new Message_DragClaim flags bit 0 is clear, program the pointer shape to <u>ptr_drop</u>;</li> <li><u>if old_dragclaim_flags bit 1 is set, but the new Message_DragClaim flags bit 1 is clear, call Wimp_DragBox (with a drag type of 5), DragASprite_Start or DragAnObject_Start as appropriate.</u></li> <li><u>if old_dragclaim_flags bit 1 is clear, but the new Message_DragClaim flags bit 1 is set, call DragASprite_Stop or DragAnObject_Stop if necessary, then call Wimp_DragBox with a drag type of 7.</u></li> </ul> <li><u>else,</u></li> <ul> <li><i>claim is just starting</i></li> <li><u>if Message_DragClaim flags bit 1 is set, call DragASprite_Stop or DragAnObject_Stop if necessary, then call Wimp_DragBox with a drag type of 7.</u></li> </ul> <li>set claimant to task handle in Message_DragClaim;</li> <li>set lastref to my_ref of Message_DragClaim;</li> <li><u>set old_dragclaim_flags to flags word from Message_DragClaim.</u></li> </ul> </ul> <li>When Message_Dragging bounces,</li> <ul> <li>if claimant is not 'none',</li> <ul> <li><i>claimant is releasing claim (including when claimant doesn't reply because the drag is aborting)</i></li> <li><u>if drag_finished is 'false',</u></li> <ul> <li>if old_dragclaim_flags bit 0 is set, program the pointer shape to <u>ptr_drop</u>;</li> <li><u>if old_dragclaim_flags bit 1 is set, call Wimp_DragBox (with a drag type of 5), DragASprite_Start or DragAnObject_Start as appropriate.</u></li> </ul> <li>set claimant to 'none';</li> <li><u>set lastref to 'none';</u></li> <li>resend Message_Dragging as message type 17/18 to the window owner (preserving the flags, and with your_ref = 0).</li> </ul> <li>else,</li> <ul> <li><i>(no claimant is in effect AND drag has finished) OR the drag is aborting</i></li> <li>if drag_finished is 'true' <i>(this comparison is not strictly necessary, since drag_aborted also implies drag_finished)</i>,</li> <ul> <li>if drag_aborted is 'false',</li> <ul> <li>initiate simple drop operation (send Message_DataSave to window owner, using native data type and your_ref = 0).</li> </ul> </ul> </ul> </ul> </ul> <p /> <b>Claiming task:</b> <ul> <li>At <u>initialisation</u>,</li> <ul> <li>set claiming to 'false'.</li> </ul> <li>When Message_Dragging is received,</li> <ul> <li>if claiming is 'false',</li> <ul> <li>if flags bit 4 is clear,</li> <ul> <li><i>start claim</i></li> <li><u>set claiming to 'true' and autoscrolling to 'false';</u></li> <li>if pointer is in the autoscroll pause zone,</li> <ul> <li><u>set pausing to 'true';</u></li> <li><u>set old_pointer_x, old_pointer_y and old_pointer_time to the x and y from Message_Dragging and the current monotonic time;</u></li> <li>program pointer to autoscroll-pause shape, <u>and set pointer_altered to 'true';</u></li> </ul> <li><u>else,</u></li> <ul> <li><u>set pausing to 'false' and pointer_altered to 'false';</u></li> </ul> <li><u>if the data type is suitable,</u> draw the ghost caret (I-beam or bounding box) and <u>set ghost_caret to 'true', else set ghost_caret to 'false';</u></li> <li>reply with Message_DragClaim (message type 17), <u>using pointer_altered and ghost_caret to determine the flags.</u></li> </ul> </ul> <li>else,</li> <ul> <li>if flags bit 4 is clear AND (claiming task owns the window<u>/icon</u> handle in Message_Dragging OR autoscrolling is 'true'),</li> <ul> <li><i><u>update claim</u></i></li> <li>if pausing is 'true',</li> <ul> <li>if current pointer x or y differs from old_pointer_x or old_pointer_y, set old_pointer_x, old_pointer_y and old_pointer_time to the current pointer x and y and monotonic time;</li> <li>if pointer has left autoscroll pausing zone,</li> <ul> <li>set pausing and pointer_altered to 'false';</li> </ul> <li> else,</li> <ul> <li>if (current monotonic time - old_pointer_time) >= pause_time (typically 0.5 seconds), set autoscrolling to 'true' and pausing to 'false', and program the pointer to its autoscroll-active shape;</li> </ul> </ul> <li>else if autoscrolling is 'false',</li> <ul> <li>if pointer is in the autoscroll pause zone,</li> <ul> <li>set pausing to 'true';</li> <li>set old_pointer_x, old_pointer_y and old_pointer_time to the x and y from Message_Dragging and the current monotonic time;</li> <li>program pointer to autoscroll-pause shape, and set pointer_altered to 'true';</li> </ul> <li>else,</li> <ul> <li>set pausing to 'false' and pointer_altered to 'false';</li> </ul> </ul> <li>else (i.e. autoscrolling is 'true'),</li> <ul> <li>if pointer is over the window, but not in the autoscroll pause zone,</li> <ul> <li>set autoscrolling and pointer_altered to 'false';</li> </ul> <li>else,</li> <ul> <li>scroll the window by an amount proportional to the distance from the pointer to the inside edge of the autoscroll pause zone;</li> <li>if the window cannot be scrolled any further in this direction (or can be scrolled in neither direction if a 2D scroll), set autoscrolling to 'false', set pausing to 'true' and program the pointer to its autoscroll-pausing shape;</li> </ul> </ul> <li>if ghost_caret is 'true', update ghost caret - unless the work-area-relative position is unchanged, undraw the old ghost caret and draw the new ghost caret;</li> <li>reply with Message_DragClaim (message type 17), using pointer_altered and ghost_caret to determine the flags.</li> </ul> <li>else,</li> <ul> <li><i>release claim</i></li> <li>set claiming to 'false';</li> <li><u>if ghost_caret is 'true', </u>undraw the old ghost caret;</li> <li>let Message_Dragging bounce (i.e. don't reply to it).</li> </ul> </ul> </ul> <li>When Message_DataSave is received,</li> <ul> <li>if you_ref != 0,</li> <ul> <li><u>if claiming is 'true',</u></li> <ul> <li><i>this was an enhanced (full drag-and-drop) drop - the claim was never released</i></li> <li>set claiming to 'false';</li> <li>if ghost_caret is 'true', undraw the old ghost caret;</li> <li>import data to the last ghost caret position using conventional data transfer protocol (preferably using memory data transfer).</li> </ul> <li><u>else,</u></li> <ul> <li><i>this is part of the paste protocol</i></li> <li><u>continue as for simple drop...</u></li> </ul> </ul> <li>else,</li> <ul> <li><i>this was a simple drop</i></li> <li>import data to position from Message_DataSave using conventional data transfer protocol (preferably using memory data transfer).</li> </ul> </ul> </ul> <p /> <h4>Clipboard Module</h4> <p /> <h5>Use</h5> <p /> The Clipboard module, in conjunction with the SWI Wimp_AutoScroll, will reduce the coding required to implement drag-and-drop to the following, a great improvement on §5.4.1.3. Note that, unlike the clipboard maintenance and paste protocols, the drag and drop protocols use one-to-one messages rather than broadcast messages, so the Clipboard needs to make use of filters in order to translate between the protocols. (An assumption has been made that the receiving task wishes to use an I-beam ghost caret - this does not have to be the case, but Wimp_SetCaretPosition's new facility for drawing ghost carets requires simpler but different code from that in §5.4.1.3.) <p /> <b>Sending task:</b> <ul> <li>At drag start,</li> <ul> <li>ensure sending window has the input focus;</li> <li>call SWI Clipboard_StartDrag.</li> </ul> <li>When Message_PutRequest is received,</li> <ul> <li>if flags bits 3 and 31 are clear,</li> <ul> <li><i>this is a PutRequest for the selection, rather than the task-managed clipboard</i></li> <li>translate selected data to the first possible data type in the list, or leave as the native data type if none are possible;</li> <li>call Clipboard_Put to send the data;</li> <li>if flags bit 4 of the Message_PutRequest was set, delete the selection.</li> </ul> </ul> </ul> <p /> <b>Claiming task:</b> <ul> <li>At initialisation,</li> <ul> <li>set claiming to 'false'.</li> </ul> <li>When Message_Dragging is received,</li> <ul> <li>if claiming is 'false',</li> <ul> <li>if flags bit 4 is clear,</li> <ul> <li><i>start claim</i></li> <li>set claiming to 'true';</li> <li>call Wimp_AutoScroll;</li> <li>call Wimp_SetCaretPosition to position the ghost caret if at least one available data type is suitable;</li> <li>reply with Message_DragClaim (message type 17), with flags bit 0 clear, and flags bit 1 set if a ghost caret is being displayed.</li> </ul> </ul> <li>else,</li> <ul> <li>if flags bit 4 is clear AND (claiming task owns the window handle in Message_Dragging OR Wimp_AutoScroll indicates scrolling is in progress),</li> <ul> <li><i>update claim</i></li> <li>call Wimp_SetCaretPosition to reposition the ghost caret if at least one available data type is suitable;</li> <li>reply with Message_DragClaim (message type 17), with flags bit 0 clear, and flags bit 1 set if a ghost caret is being displayed.</li> </ul> <li>else,</li> <ul> <li><i>release claim</i></li> <li>set claiming to 'false';</li> <li>call Wimp_AutoScroll to deactivate autoscrolling;</li> <li>call Wimp_SetCaretPosition -1 to remove the ghost caret;</li> <li>let Message_Dragging bounce (i.e. don't reply to it).</li> </ul> </ul> </ul> <li>When Message_DataSave is received,</li> <ul> <li>if claiming is 'true',</li> <ul> <li><i>this was an enhanced (full drag-and-drop) drop - the claim was never released</i></li> <li>set claiming to 'false';</li> <li>call Wimp_AutoScroll to deactivate autoscrolling;</li> <li>call Wimp_SetCaretPosition -1 to remove the ghost caret;</li> <li>copy window handle, icon handle, x and y offsets from last Message_Dragging over the Message_DataSave block equivalents, and call Clipboard_CatchDrop.</li> </ul> <li>else,</li> <ul> <li><i>this was a simple drop</i></li> <li>call Clipboard_CatchDrop.</li> </ul> </ul> </ul> </ul> <p /> <p /> <h5>Messaging</h5> <p /> The details of the new SWIs introduced are: <p /> <table cellpadding=5> <tr><td colspan=6><b>SWI Clipboard_StartDrag (&4E003)</b> <tr><td> <td colspan=5>Starts a drag-and-drop drag, using the Clipboard as a proxy. <tr><td colspan=6>On entry <tr><td> <td>R0 = <td>flags: <td>bit 1 <td>=> <td>as Message_Dragging (= sending from selection) <tr><td> <td> <td> <td>bit 2 <td>=> <td>as Message_Dragging (= sending from clipboard) <tr><td> <td> <td> <td>bits 14, 15 <td> 0 <td>=> use rotating-dash fixed-size Wimp dragbox <tr><td> <td> <td> <td> <td> 1 <td>=> use DragASprite <tr><td> <td> <td> <td> <td> 2 <td>=> use DragAnObject <tr><td> <td> <td> <td> <td> 3 <td>=> reserved <tr><td> <td> <td> <td>bit 16 <td>=> <td>as DragAnObject_Start, if applicable (R1 is a pointer to a routine rather than a SWI number) <tr><td> <td> <td> <td>bit 17 <td>=> <td>as DragAnObject_Start, if applicable (if bit 16 is set and bit 18 clear, enter routine with R10 below R13 - note this was previously misdocumented as the routine being entered in SVC mode rather than USR mode) <tr><td> <td> <td> <td>bit 18 <td>=> <td>as DragAnObject_Start, if applicable (if bit 16 is set and DragAnObject is version 0.09 or later, enter routine in USR mode rather than SVC mode) <tr><td> <td> <td> <td>bit 31 set <td>=> <td>flag reply messages as for the attention of the Wimp (this bit must only be set by the Wimp) <tr><td> <td> <td> <td colspan=3>all others are reserved and must be clear <tr><td> <td>R1 = <td colspan=4>sprite area or renderer (if DragASprite or DragAnObject, respectively) <tr><td> <td>R2 = <td colspan=4>pointer to sprite name or register/parameter block (if DragASprite or DragAnObject, respectively) <tr><td> <td>R3 = <td colspan=4>source window handle (used in combination with the Shift key state to determine when the source data needs deleting afterwards) <tr><td> <td>R4 = <td colspan=4>pointer to word-aligned block containing three bounding boxes, each made up of four 32-bit quantities held in the order xmin, ymin, xmax, ymax, where the minima are inclusive and the maxima are exclusive: <OL> <li>bounding box to apply to the pointer, in OS units from the screen origin; if xmin > max then the pointer is constrained to the screen</li> <li>initial position of the dragbox/sprite/object being dragged, in OS units from the screen origin</li> <li>"real" position and size of the data to use to render the ghost caret, in millipoints (1/72000ths of an inch) relative to the pointer; if xmin > xmax then the size is unknown or undefined</li> </OL> <tr><td> <td>R5 = <td colspan=4>data length, bytes <tr><td> <td>R6 = <td colspan=4>pointer to non-null list of data types that the task can translate the data to (in no particular order), terminated by -1 <tr><td> <td>R7 = <td colspan=4>pointer to proposed leafname of data, null-terminated <tr><td colspan=6>On exit <tr><td> <td colspan=5>R0-R7 preserved <tr><td> <td colspan=5>The Clipboard takes a copy of the data pointed to, and performs the actions described in §5.4.1.3 (sending) on behalf of the task. In order to achieve this, it forces the required Wimp events to be unmasked using a pre-poll filter, then performs its main actions using a post-poll filter; it also calls Wimp_AddMessages, so it not necessary for the task to register interest in Message_DragClaim etc. at initialisation. During the drag, the task will not see any user_drag_box events, key_pressed events (except for Escape), or any DragClaim, RAMFetch, DataSaveAck or DataLoadAck messages. If null events were enabled in the poll mask before it was massaged by the pre-poll filter (and, if it was a call to Wimp_PollIdle, the required time has passed) they will also pass through to the task once the post-poll filter has done its work. <tr><td> <td colspan=5>When the drag ends (successfully or not), the filters are removed. When the drag ends successfully, the task's cooperation is required in order to translate the data to the required data type; this is accomplished by the Clipboard sending it a Message_PutRequest with flags bit 3 clear, as described in §5.3.2.1. </table> <p /> <table cellpadding=5> <tr><td colspan=6><b>SWI Clipboard_CatchDrop (&4E004)</b> <tr><td> <td colspan=5>Request the Clipboard to act as a proxy for data transfer during a drop. <tr><td colspan=6>On entry <tr><td> <td>R0 = <td>flags: <td>bit 31 set <td>=> <td>flag reply messages as for the attention of the Wimp (this bit must only be set by the Wimp) <tr><td> <td> <td> <td colspan=3>all others are reserved and must be clear <tr><td> <td>R1 = <td colspan=4>pointer to DataSave message block (or DataLoad message block if initiated by the Filer) that needs replying to <tr><td colspan=6>On exit <tr><td> <td colspan=5>R0-R1 preserved <tr><td> <td colspan=5>The Clipboard handles the data transfer for the task, trying memory data transfer first if possible. When the transfer is complete, the Clipboard sends a Message_Paste to the task that called this SWI, so as to appear identical to a paste operation. <tr><td> <td colspan=5>It will also detect if it sent the DataSave message itself - in other words, if the sending task was using the Clipboard as a proxy too - if so, no further messaging will occur, and the Clipboard will simply use the pointer to its copy of the data made during Clipboard_Put in the Message_Paste. </table> <p /> <h4>Writable Icons</h4> <p /> The Wimp will handle drags to and from writable icons as in §5.4.2. <p /> The Wimp will install an internal message filter in order to listen for Clipboard messages (Message_PutRequest and Message_Paste) with flags bit 31 set; these are handled by the Wimp and not passed on to the task. Similarly, it will intercept and not pass on Message_Dragging throughout any period when it is claiming the drag. However, some tasks (such as FrontEnd) do perform useful functions when they receive a Message_DataSave, so Message_DataSave is always passed through to the task, and the Wimp will only call Clipboard_CatchDrop at the Wimp_Poll following the delivery of Message_DataSave if the task didn't call Wimp_SendMessage, Wimp_UpdateWindow or Wimp_ForceRedraw. </ul> <p /> <h2>Data Formats</h2> <p /> No new data formats are introduced. <p /> <h2>Dependencies</h2> <p /> The new Wimp provides facilities not available in earlier versions. Although the source release means that it is possible for applications that use them to require users of older Wimps to upgrade them, the authors may choose to implement them manually in cases where an older Wimp is detected. However, it is encouraged that the new Wimp facilities be utilised when possible, to accommodate future GUI changes, to allow system-wide configuration of autoscroll behaviour and so on. <p /> The Wimp will require the Clipboard to enable functioning of drag-and-drop to or from writable icons. Without it, selections will be able to be made, but no operations (other than deletion) can be performed on them, and no selections from other applications will be inserted when dropped on a writable icon. <p /> <h2>Acceptance Test</h2> <p /> <h3>Clipboard Module</h3> <p /> <h4>Compatibility</h4> <p /> The most advanced features of RISC OS that the Clipboard will make use of are Dynamic Areas and the DragAnObject module, both introduced at RISC OS 3.50. Provision may be made for further development work to be done to support versions back to RISC OS 3.10 (by using RMA rather than Dynamic Areas, and defaulting to rotating-dash boxes when a DragAnObject drag is requested), but for the purposes of the initial release, a modern OS may be assumed. <p /> <h4>Reliability/Robustness</h4> <p /> The module must be able to handle at least a thousand consecutive operations without crashing. Null-length data, extremely long data and data close in length to a multiple of the page size must not cause problems. Bad parameters (e.g. illegal sprite area pointers) must be handled as well as possible - in the example, a rotating-dash box must be used instead. <p /> <h4>Performance</h4> <p /> Performance will unfortunately continue to be slow in certain key situations - for example, when transferring data to a conventional task by memory data transfer, where the receiving task has specified too small a buffer. Memory transfer will be slower during drops, since the data is copied twice, once to the Clipboard's application slot, and once from it. The incidences of scrapfile transfer will however be reduced, resulting in speed gains. <p /> <h4>Memory Usage</h4> <p /> The module itself must not exceed 32kB in length. Stored global clipboard data and transient data (during a drop operation) are stored in the Clipboard's application slot so that the only size limits are those of the application slot size (not a big issue with modern memory maps) and the amount of physical RAM available. The application slot shall grow and shrink so that it is no larger than the combined size of the data stored, rounded up to the next page boundary. The RMA shall be used for general heap storage (linked lists etc.). <p /> <h3>Wimp Writable Icon Code</h3> <p /> <h4>Compatibility</h4> <p /> The writable icon code will function correctly for all tasks that follow the revised guidelines in §5 and all tasks that do not support the drag-and-drop protocol, but it may lack complete functionality (although not to the extent of rendering it useless) for up to 10% of the writable icons in existing applications written to the old application note guidelines. <p /> <h4>Reliability/Robustness</h4> <p /> The writable icon cut-and-paste / drag-and-drop code must be at least as reliable as the Clipboard module. <p /> <h4>Performance</h4> <p /> Redraw of writable icons, especially when delimiting a selection with autoscrolling active, must not cause flicker. Data transfer operations must not be appreciably slower than the Clipboard routines that are actually doing the work. <p /> <h4>Memory Usage</h4> <p /> Writable icon data is usually held in application workspace, and will not increase in size by virtue of these enhancements. A negligible amount of extra module workspace will be required to hold the details of the Wimp selection and ghost caret, this should typically be no more than 32K. <p /> <h2>Non Compliances</h2> <p /> No attempt will be made to develop an selection-drawing algorithm that can cope with overlapping icons. The appearance of such icons after scrolling and redrawing is not defined. <p /> <h2>Development Test Strategy</h2> <p /> Test applications will be written to exercise the Clipboard SWIs. <p /> Drags to and from the existing drag-and-drop applications (e.g. DataPower, EasiWriter and TechWriter) work seamlessly. These applications will therefore be important testing tools. Also for testing purposes, a drag-and-drop trashcan application and simple clipboard-display application will be written. <p /> (Conventional data transfer (as for example, when dropping a selection on to a Filer window) is not expected to cause significant problems, as the protocol has been clearly defined for a long time, unlike the protocol in the application notes.) <p /> A test suite will be written to exercise the functions of the Clipboard through exercise of writable icons' cut-and-paste / drag-and-drop facilities. For example: setting of writable icon selections will be tested repeatedly, involving operations that change one or both ends of a selection (or neither) at the same time, both with and without the presence of a ghost caret. This will be done by direct calling of Wimp_SetCaretPosition. And text files of differing length, of differing line terminator and files that have been accidentally mistyped as text will be saved on to writable icons of differing validation strings, using conventional data transfer, pasting and dropping. <p /> <h2>Product Organisation</h2> <p /> This document, and the code it describes, form part of the Shared Source RISC OS release. <p /> The APIs and messages should ideally be included in a new version of the Programmer's Reference Manual. Use of the raw protocol rather than the Clipboard module will be deprecated. <p /> The Clipboard module can be softloaded, but must also be capable of being built into ROM. <p /> <h2>Future Enhancements</h2> <p /> None planned. <p /> <h2>Glossary</h2> <p /> <table cellpadding=3> <tbody VALIGN=TOP> <tr><td><strong>AND</strong> <i>conj.</i> <td>Logical AND. <tr><td><strong>Caret</strong> <i>n.</i> <td>The position in a document where typed characters or pasted clipboard contents will be placed. Many pre-drag-and-drop applications also use this position as the insertion point for dropped data, but drag-and-drop applications must use the ghost caret for this purpose instead. In textual documents, the caret is often shown by a red I-beam, but other representations of the caret may be more appropriate for other kinds of data. Some editors, such as !Draw, do not have a visible insertion point, but still "grab the caret" and mark it as invisible, in order to gain the input focus so that they may receive keystroke events. <tr><td><strong>Clear</strong> <i>v.</i> <td>The operation by which a selection is undone. <tr><td><strong>Clipboard</strong> <i>n.</i> <td>A hidden, temporary storage area that holds any type of data while the user is copying or moving it using the cut-and-paste protocol, whether internal to one application, or between applications. Conceptually, there is only one clipboard, but the actual storage area may actually be managed by different applications or modules, depending upon the circumstances. <tr><td> <td>The term may also be used to refer to the Clipboard module, although in this eventuality, the initial letter will be in upper case. <tr><td><strong>Copy</strong> <i>v.</i> <td>The operation by which the current selection is replicated in the clipboard, overwriting any existing data in the clipboard. <tr><td><strong>Cut</strong> <i>v.</i> <td>As copy, but the selection is subsequently deleted from its original location. <tr><td><strong>Data type</strong> <i>n.</i> <td>A value equivalent to a filetype, but not necessarily referring to a file. <tr><td><strong>Drag</strong> <i>v.</i> <td>The operation by which the user indicates where they wish a selection to be copied or moved to by dragging a representation of the data from the selection to the destination. <tr><td><strong>Drop</strong> <i>v.</i> <td>At the end of a drag, the actual data transfer process. This combines the functionality of a paste operation with either a cut or copy operation, as appropriate. <tr><td><strong>Ghost caret</strong> <i>n.</i> <td>During a drag operation, the position in a document where the data would be inserted, were the user to release the mouse button. In textual documents, the ghost caret is often shown similarly to a normal caret, but coloured grey, and "snapped" to the nearest character boundary. Other documents might better display the ghost caret as the bounding box of the data, scaled according to the destination window's zoom factor(s). <tr><td><strong>OR</strong> <i>conj.</i> <td>Logical inclusive OR (i.e. not EOR) - used where the 'or' would have an ambiguous meaning, for example in English text. <tr><td><strong>Input focus</strong> <i>n.</i> <td>The defining attribute of the window where keystroke events will be delivered. The user may be able to see a caret or a selection, or possibly neither, in the window that has the input focus; the window border will be coloured in an alternative colour (conventionally cream). Any parent nested windows (recursively), and any non-pane window behind a pane window, will also have their title bars recoloured. <tr><td><strong>Paste</strong> <i>v.</i> <td>The operation that the user performs to copy the clipboard contents into a document, at the caret. <tr><td><strong>Selection</strong> <i>n.</i> <td>The portion of a document which the user has chosen as the target for subsequent operations. This may be a contiguous selection (as in the case of selected text) or a non-contiguous selection (as in the case of a number of selected files in the Filer). The rendering of the selection is media-dependent, but typically may be shown by inversion of the colours of the selected region, or alternatively by the drawing of a bounding box around the selection(s). <tr><td> <td>A <i>shaded</i> selection, which ought be rendered to match the Wimp's rendering of shaded selections in writable icons, indicates the location of a selection after another selection has been made in another window - but not when a caret or selection is made in a non-drag-and-drop application. <tr><td><strong>Shadow caret</strong> <i>n.</i> <td>The equivalent of a shaded selection, but for carets. A shadow caret must not be rendered in such a way that it can be mistaken for a ghost caret. It is optional, because applications are expected normally to use a Wimp-drawn caret, and the Wimp does not support shadow carets. However, shadow carets can be useful, especially if the application draws its own caret anyway (as, for example, if an I-beam is an unsuitable), because they fix an insertion point for a drop, whenever one or both of the sending and receiving tasks uses pre-drag-and-drop data transfer protocol. The shadow caret is also the position to which the caret will be returned if the user Adjust-clicks on the window, or clicks in a "dead" region of the window, such as a page border; this is particularly useful in cases where repositioning the caret would be time-consuming or fiddly, for example if the caret is in a deep "layer" of a document. </tbody> </table> <p /> <h2>References</h2> <p /> [1]: Support Group Application Note 240: <i>The RISC OS Selection Model and Clipboard</i> <p /> [2]: Support Group Application Note 241: <i>The RISC OS Drag-and-Drop System</i> <p /> [3]: RISC OS 3 PRM <strong>3</strong> §53: <i>The Window Manager</i>, pp 3-249 - 3-256 <p /> [4]: [[Style Guide|RISC OS Style Guide]], issue 3, §11: <i>Handling selection</i>, pp 77-82 <p /> [5]: Document Ref 1309,413/FS: <i>Ursula Window Manager Changes Functional Specification</i> <p /> <h2>History</h2> <div align="left"> <table BORDER=1 cellpadding=4> <tr><td align="center"><b>Revision</b> <td align="center"><b>Who</b> <td align="center"><b>Date</b> <td><b>Comment</b> <tr><td align="center">A (aka 0.00) <td align="center">BJGA <td align="center">12-09-1997 <td>Started <tr><td align="center">B (aka 0.01) <td align="center">BJGA <td align="center">13-10-1997 <td>First release for comment <tr><td align="center">C (aka 0.02) <td align="center">BJGA <td align="center">14-10-1997 <td>Released for review <tr><td align="center">D <td align="center">BJGA <td align="center">19-05-1998 <td>Prepared for D.O. <tr><td align="center">E <td align="center">BJGA <td align="center">26-02-1999 <td>Started reworking document for Java 1.2 project, didn't get far before cancelled again <tr><td align="center">F <td align="center">BJGA <td align="center">16-10-2007 <td>Finally finished integrating the Ursula review comments and 8 years' worth of mental notes, for initial release alongside shared source code <tr><td align="center">G <td align="center">RPS <td align="center">22-02-2015 <td>Updated the page references in the Style Guide </table> </div> <p /> <h2>Related resources</h2> <p /> <a href="/images/risc_os_open/specifications/clipboard/state_diagram.pdf">State diagram</a> (PDF format, 8K). </notextile>