From f8f5d753035ad7eae2f6fde77a6a27a15da1bed7 Mon Sep 17 00:00:00 2001 From: George Peter Staplin Date: Fri, 19 Sep 2008 00:02:48 -0600 Subject: [PATCH] XQuartz: pbproxy: Add COMPOUND_TEXT handling. Do misc. cleanups with testing to verify that the behavior didn't change. main.m: XInternAtom compound_text, and atom_pair. pbproxy.h: Add compound_text and atom_pair to the struct atom_list. x-selection.m: Add an #include of Xutil.h. Refactor the reply struct initialization to be done in a common place. Add send_reply: to simplify the code a bit more. Add send_compound_text: which handles the COMPOUND_TEXT type. Add the beginnings of a send_multiple:. Change handle_image:extension: to handle_image:. The extension: message isn't needed anymore. (cherry picked from commit 1e9460abdf5bafe46215966bbef3e796cb1c33e0) --- hw/xquartz/pbproxy/main.m | 2 + hw/xquartz/pbproxy/pbproxy.h | 3 +- hw/xquartz/pbproxy/x-selection.m | 199 +++++++++++++++++++------------ 3 files changed, 124 insertions(+), 80 deletions(-) diff --git a/hw/xquartz/pbproxy/main.m b/hw/xquartz/pbproxy/main.m index 4b1dac19f..7577f7a99 100644 --- a/hw/xquartz/pbproxy/main.m +++ b/hw/xquartz/pbproxy/main.m @@ -77,6 +77,8 @@ static void x_init (void) { atoms->incr = XInternAtom (x_dpy, "INCR", False); atoms->atom = XInternAtom (x_dpy, "ATOM", False); atoms->clipboard_manager = XInternAtom (x_dpy, "CLIPBOARD_MANAGER", False); + atoms->compound_text = XInternAtom (x_dpy, "COMPOUND_TEXT", False); + atoms->atom_pair = XInternAtom (x_dpy, "ATOM_PAIR", False); if (!XAppleWMQueryExtension (x_dpy, &x_apple_wm_event_base, &x_apple_wm_error_base)) { diff --git a/hw/xquartz/pbproxy/pbproxy.h b/hw/xquartz/pbproxy/pbproxy.h index ad8f2e4e4..098e309bc 100644 --- a/hw/xquartz/pbproxy/pbproxy.h +++ b/hw/xquartz/pbproxy/pbproxy.h @@ -25,7 +25,8 @@ extern int x_apple_wm_event_base, x_apple_wm_error_base; struct atom_list { Atom primary, clipboard, text, utf8_string, string, targets, multiple, - cstring, image_png, image_jpeg, incr, atom, clipboard_manager; + cstring, image_png, image_jpeg, incr, atom, clipboard_manager, + compound_text, atom_pair; }; extern struct atom_list *atoms; diff --git a/hw/xquartz/pbproxy/x-selection.m b/hw/xquartz/pbproxy/x-selection.m index 9eca6c7ce..1b660abe6 100644 --- a/hw/xquartz/pbproxy/x-selection.m +++ b/hw/xquartz/pbproxy/x-selection.m @@ -338,6 +338,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) #if 0 if ([_pasteboard changeCount] != _my_last_change) { + /*gstaplin: we should perhaps investigate something like this branch above...*/ if ([_pasteboard availableTypeFromArray: _known_types] != nil) { /* Pasteboard has data we should proxy; I think it makes @@ -493,6 +494,25 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) atoms->clipboard)); } +- (void) init_reply:(XEvent *)reply request:(XSelectionRequestEvent *)e +{ + reply->xselection.type = SelectionNotify; + reply->xselection.selection = e->selection; + reply->xselection.target = e->target; + reply->xselection.requestor = e->requestor; + reply->xselection.time = e->time; + reply->xselection.property = None; +} + +- (void) send_reply:(XEvent *)reply +{ + /* + * We are supposed to use an empty event mask, and not propagate + * the event, according to the ICCCM. + */ + XSendEvent (x_dpy, reply->xselection.requestor, False, 0, reply); +} + /* * This responds to a TARGETS request. * The result is a list of a ATOMs that correspond to the types available @@ -506,27 +526,24 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) XEvent reply; NSArray *pbtypes; - reply.xselection.type = SelectionNotify; - reply.xselection.selection = e->selection; - reply.xselection.target = e->target; - reply.xselection.requestor = e->requestor; - reply.xselection.time = e->time; - reply.xselection.property = None; + [self init_reply:&reply request:e]; pbtypes = [_pasteboard types]; if (pbtypes) { - long list[5]; + long list[6]; long count = 0; if ([pbtypes containsObject:NSStringPboardType]) { - /* We have a string type that we can convert to a UTF8 or Latin-1 string. */ + /* We have a string type that we can convert to UTF8, or Latin-1... */ DB ("NSStringPboardType\n"); list[count] = atoms->utf8_string; ++count; list[count] = atoms->string; ++count; + list[count] = atoms->compound_text; + ++count; } if ([pbtypes containsObject:NSTIFFPboardType] @@ -540,7 +557,6 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) ++count; } - if (count) { /* We have a list of ATOMs to send. */ @@ -551,46 +567,10 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) } } - /* - * We are supposed to use an empty event mask, and not propagate - * the event, according to the ICCCM. - */ - XSendEvent (x_dpy, e->requestor, False, 0, &reply); + [self send_reply:&reply]; } -/*TODO finish this - it's flawed. */ -- (void) send_multiple:(XSelectionRequestEvent *)e -{ -#if 0 - XEvent reply; - int i, nitems; - unsigned long *atoms; - - if (None == e->property) - return; - - atoms = read_prop_32 (e->requestor, e->property, &nitems); - - if (atoms != NULL) - { - data = [_pasteboard stringForType:NSStringPboardType]; - - for (i = 0; i < nitems; i += 2) - { - Atom target = atoms[i], prop = atoms[i+1]; - - atoms[i+1] = convert_1 (e, data, target, prop); - } - - XChangeProperty (x_dpy, e->requestor, e->property, target, - 32, PropModeReplace, (unsigned char *) atoms, - nitems); - XFree (atoms); - } -#endif -} - - (void) send_string:(XSelectionRequestEvent *)e utf8:(BOOL)utf8 { XEvent reply; @@ -598,12 +578,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) TRACE (); - reply.xselection.type = SelectionNotify; - reply.xselection.selection = e->selection; - reply.xselection.target = e->target; - reply.xselection.requestor = e->requestor; - reply.xselection.time = e->time; - reply.xselection.property = None; + [self init_reply:&reply request:e]; pbtypes = [_pasteboard types]; @@ -615,7 +590,8 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) const char *bytes; NSUInteger length; - if (utf8) { + if (utf8) + { bytes = [data UTF8String]; /* * We don't want the UTF-8 string length here. @@ -623,7 +599,9 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) */ length = [data lengthOfBytesUsingEncoding:NSASCIIStringEncoding]; DB ("UTF-8\n"); - } else { + } + else + { DB ("Latin-1\n"); bytes = [data cStringUsingEncoding:NSISOLatin1StringEncoding]; length = [data lengthOfBytesUsingEncoding:NSASCIIStringEncoding]; @@ -638,10 +616,77 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) } } - /* Always send a response, even if the property value is None. */ - XSendEvent (x_dpy, e->requestor, False, 0, &reply); + [self send_reply:&reply]; } +- (void) send_compound_text:(XSelectionRequestEvent *)e +{ + XEvent reply; + NSArray *pbtypes; + + TRACE (); + + [self init_reply:&reply request:e]; + + pbtypes = [_pasteboard types]; + + if ([pbtypes containsObject: NSStringPboardType]) + { + NSString *data = [_pasteboard stringForType:NSStringPboardType]; + if (nil != data) + { + /* + * Cast to (void *) to avoid a const warning. + * AFAIK Xutf8TextListToTextProperty does not modify the input memory. + */ + void *utf8 = (void *)[data UTF8String]; + char *list[] = { utf8, NULL }; + XTextProperty textprop; + + textprop.value = NULL; + + if (Success == Xutf8TextListToTextProperty (x_dpy, list, 1, + XCompoundTextStyle, + &textprop)) + { + + if (8 != textprop.format) + DB ("textprop.format is unexpectedly not 8 - it's %d instead\n", + textprop.format); + + XChangeProperty (x_dpy, e->requestor, e->property, + atoms->compound_text, textprop.format, + PropModeReplace, textprop.value, + textprop.nitems); + + reply.xselection.property = e->property; + } + + if (textprop.value) + XFree (textprop.value); + } + } + + [self send_reply:&reply]; +} + +- (void) send_multiple:(XSelectionRequestEvent *)e +{ + XEvent reply; + + TRACE (); + + [self init_reply:&reply request:e]; + + if (None != e->property) + { + + } + + [self send_reply:&reply]; +} + + - (void) send_image:(XSelectionRequestEvent *)e { XEvent reply; @@ -651,12 +696,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) TRACE (); - reply.xselection.type = SelectionNotify; - reply.xselection.selection = e->selection; - reply.xselection.target = e->target; - reply.xselection.requestor = e->requestor; - reply.xselection.time = e->time; - reply.xselection.property = None; + [self init_reply:&reply request:e]; pbtypes = [_pasteboard types]; @@ -678,7 +718,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) if (type) { NSData *data; - data = [_pasteboard dataForType: type]; + data = [_pasteboard dataForType:type]; if (data) { @@ -709,8 +749,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) } } } - /* Always send a response, even if the property value is None. */ - XSendEvent (x_dpy, e->requestor, False, 0, &reply); + [self send_reply:&reply]; } - (void)send_none:(XSelectionRequestEvent *)e @@ -719,15 +758,8 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) TRACE (); - reply.xselection.type = SelectionNotify; - reply.xselection.selection = e->selection; - reply.xselection.target = e->target; - reply.xselection.requestor = e->requestor; - reply.xselection.time = e->time; - reply.xselection.property = None; - - /* Always send a response, even if the property value is None. */ - XSendEvent (x_dpy, e->requestor, False, 0, &reply); + [self init_reply:&reply request:e]; + [self send_reply:&reply]; } @@ -746,7 +778,8 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) * Perhaps we should just punt and ignore races. */ - /*TODO handle COMPOUND_STRING... We need a test app*/ + /*TODO we need a COMPOUND_TEXT test app*/ + /*TODO we need a MULTIPLE test app*/ DB ("e->target %s\n", XGetAtomName (x_dpy, e->target)); @@ -766,7 +799,15 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) else if (e->target == atoms->string) { [self send_string:e utf8:NO]; - } + } + else if (e->target == atoms->compound_text) + { + [self send_compound_text:e]; + } + else if (e->target == atoms->multiple) + { + [self send_multiple:e]; + } else if (e->target == atoms->image_png || e->target == atoms->image_jpeg) { [self send_image:e]; @@ -919,7 +960,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) /* This handles the image type of selection (typically in CLIPBOARD). */ /* We convert to a TIFF, so that other applications can paste more easily. */ -- (void) handle_image: (struct propdata *)pdata extension:(NSString *)fileext +- (void) handle_image: (struct propdata *)pdata { NSArray *pbtypes; NSUInteger length; @@ -1041,11 +1082,11 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret) } else if (type == atoms->image_png) { - [self handle_image:pdata extension:@".png"]; + [self handle_image:pdata]; } else if (type == atoms->image_jpeg) { - [self handle_image:pdata extension:@".jpeg"]; + [self handle_image:pdata]; } else if (type == atoms->utf8_string) {