The destination procedure is rather short; most of the serious work on the destination side is done in the widget's transfer procedure. The transfer procedure of ExmStringTransfer is called TransferProc. UTM calls TransferProc when the source has finished converting a target. TransferProc must do the following:
A transfer procedure has the same function prototype as any Motif callback. Motif passes the transfer procedure an XmSelectionCallbackStruct pointer as the client_data argument. The targets member of this callback structure holds the name of the target converted by the source widget. For example, TransferProc calls XmTransferValue as follows to request a particular target:
XmTransferValue(ss -> transfer_id, target, (XtCallbackProc) TransferProc, NULL, 0);
When the source widget finishes the conversion, UTM calls TransferProc again.
When the source widget finishes converting the desired target, TransferProc must paste the text into the ExmStringTransfer widget. To simplify things, TransferProc overwrites whatever text was previously displayed. For more sophisticated widgets, you will have to determine how to insert the transferred text without overriding the previous text.
ExmStringTransfer displays the contents of the ExmNcompoundString resource. This resource holds an XmString value. Therefore, TransferProc must take the text that the source widget transferred and convert it into XmString format. If the source widget transferred the text as an _MOTIF_COMPOUND_STRING target, then TransferProc will have an easy time converting to XmString. If the source widget has transferred the text as some other target, then the conversion will be more difficult. For example, the following code from TransferProc handles the situation where the source widget transferred the text as COMPOUND_TEXT:
if (ss -> type == COMPOUND_TEXT) { /* Convert compound text to a compound string. * Note that XmCvtCTToXmString does not convert a list of compound text * strings, so we will get only the first if there's more than one. * XmCvtCTToXmString expects a NULL-terminated compound text string, * so add a trailing NULL. */ char *string; string = XtMalloc(ss -> length + 1); (void) memcpy(string, ss -> value, ss -> length); string[ss -> length] = ' '; cstring = XmCvtCTToXmString(string); XtFree(string); transferred = True; }
TransferProc contains similar code that converts text in other targets to XmString format. Eventually, TransferProc uses XtSetValues to assign the transferred XmString to the ExmNcompoundString resource as follows:
if (transferred) { /* We have a compound string. Use it as the new value of * ExmNcompoundString. */ Arg args[1]; Cardinal n; n = 0; XtSetArg(args[n], ExmNcompoundString, cstring); n++; XtSetValues(w, args, n); }
In a typical text transfer, the source widget is capable of converting multiple textual targets. The destination widget in a textual transfer needs to pick the richest of these textual targets. The routine in ExmStringTransfer that does this is called PreferredTarget. DestinationProc and TransferProc call PreferredTarget when the source widget returns its list of supported targets.
PreferredTarget uses the following algorithm to determine which textual target to pick. If the locale atom is present, the precedence order is as follows:
If the locale atom is not present, PreferredTargets uses this order:
The code in PreferredTarget that implements the precedence is as follows:
static Atom PreferredTarget( Widget w, Atom *targets, Cardinal num_targets) { ... int n; int cs_index = -1; int ct_index = -1; int locale_index = -1; int string_index = -1; int text_index = -1; /* Which targets can the source convert? Examine the returned targets. */ for (n = 0; n < num_targets; n++) { if (targets[n] == MOTIF_C_S) cs_index = n; if (targets[n] == COMPOUND_TEXT) ct_index = n; if (targets[n] == TEXT) text_index = n; if (targets[n] == LOCALE_ATOM) locale_index = n; if (targets[n] == XA_STRING) string_index = n; } /* If the source supports the locale atom, specify the precedence order as follows. */ if (locale_index >= 0) { if (cs_index >= 0) return targets[cs_index]; if (text_index >= 0) return targets[text_index]; if (ct_index >= 0) return targets[ct_index]; if (locale_index >= 0) return targets[locale_index]; if (string_index >= 0) return targets[string_index]; } else { /* If the source does not support the locale atom, specify the precedence order as follows. */ if (cs_index >= 0) return targets[cs_index]; if (ct_index >= 0) return targets[ct_index]; if (string_index >= 0) return targets[string_index]; } return None; }