変愚蛮怒のメインリポジトリです
Revision | dc0b6f3887ac59530c30edb0f63525ec5ecfa84b (tree) |
---|---|
Time | 2003-09-17 00:16:40 |
Author | mogami <mogami@0568...> |
Commiter | mogami |
マウスによるコピー&ペーストで漢字が使えなかったので、使えるようにした。
漢字はCOMPOUND_TEXTという形式にする必要があった。
@@ -2133,23 +2133,152 @@ static void copy_x11_end(const Time time) | ||
2133 | 2133 | } |
2134 | 2134 | } |
2135 | 2135 | |
2136 | + | |
2137 | +static Atom xa_targets, xa_timestamp, xa_text, xa_compound_text; | |
2138 | + | |
2139 | +/* | |
2140 | + * Set the required variable atoms at start-up to avoid errors later. | |
2141 | + */ | |
2142 | +static void set_atoms(void) | |
2143 | +{ | |
2144 | + xa_targets = XInternAtom(DPY, "TARGETS", False); | |
2145 | + xa_timestamp = XInternAtom(DPY, "TIMESTAMP", False); | |
2146 | + xa_text = XInternAtom(DPY, "TEXT", False); | |
2147 | + xa_compound_text = XInternAtom(DPY, "COMPOUND_TEXT", False); | |
2148 | +} | |
2149 | + | |
2150 | + | |
2151 | +static Atom request_target = 0; | |
2152 | + | |
2136 | 2153 | /* |
2137 | 2154 | * Send a message to request that the PRIMARY buffer be sent here. |
2138 | 2155 | */ |
2139 | -static void paste_x11_request(const Time time) | |
2156 | +static void paste_x11_request(Atom target, const Time time) | |
2140 | 2157 | { |
2158 | + /* | |
2159 | + * It's from some sample programs on the web. | |
2160 | + * What does it mean? -- XXX | |
2161 | + */ | |
2162 | + Atom property = XInternAtom(DPY, "__COPY_TEXT", False); | |
2163 | + | |
2141 | 2164 | /* Check the owner. */ |
2142 | - if (XGetSelectionOwner(Metadpy->dpy, XA_PRIMARY) == None) | |
2165 | + if (XGetSelectionOwner(DPY, XA_PRIMARY) == None) | |
2143 | 2166 | { |
2144 | 2167 | /* No selection. */ |
2145 | 2168 | /* bell("No selection found."); */ |
2146 | 2169 | return; |
2147 | 2170 | } |
2148 | 2171 | |
2149 | - /* Request the event as a STRING. */ | |
2150 | - XConvertSelection(DPY, XA_PRIMARY, XA_STRING, XA_STRING, WIN, time); | |
2172 | + request_target = target; | |
2173 | + | |
2174 | + /* Request the event */ | |
2175 | + XConvertSelection(DPY, XA_PRIMARY, target, property, WIN, time); | |
2151 | 2176 | } |
2152 | 2177 | |
2178 | + | |
2179 | +/* | |
2180 | + * Add the contents of the PRIMARY buffer to the input queue. | |
2181 | + * | |
2182 | + * Hack - This doesn't use the "time" of the event, and so accepts anything a | |
2183 | + * client tries to send it. | |
2184 | + */ | |
2185 | +static void paste_x11_accept(const XSelectionEvent *ptr) | |
2186 | +{ | |
2187 | + unsigned long left; | |
2188 | + const long offset = 0; | |
2189 | + const long length = 32000; | |
2190 | + XTextProperty xtextproperty; | |
2191 | + errr err = 0; | |
2192 | + | |
2193 | + /* | |
2194 | + * It's from some sample programs on the web. | |
2195 | + * What does it mean? -- XXX | |
2196 | + */ | |
2197 | + Atom property = XInternAtom(DPY, "__COPY_TEXT", False); | |
2198 | + | |
2199 | + | |
2200 | + /* Failure. */ | |
2201 | + if (ptr->property == None) | |
2202 | + { | |
2203 | + if (request_target == xa_compound_text) | |
2204 | + { | |
2205 | + /* Re-request as STRING */ | |
2206 | + paste_x11_request(XA_STRING, ptr->time); | |
2207 | + } | |
2208 | + else | |
2209 | + { | |
2210 | + request_target = 0; | |
2211 | + plog("Paste failure (remote client could not send)."); | |
2212 | + } | |
2213 | + return; | |
2214 | + } | |
2215 | + | |
2216 | + if (ptr->selection != XA_PRIMARY) | |
2217 | + { | |
2218 | + plog("Paste failure (remote client did not send primary selection)."); | |
2219 | + return; | |
2220 | + } | |
2221 | + | |
2222 | + if (ptr->target != request_target) | |
2223 | + { | |
2224 | + plog("Paste failure (selection in unknown format)."); | |
2225 | + return; | |
2226 | + } | |
2227 | + | |
2228 | + /* Get text */ | |
2229 | + if (XGetWindowProperty(Metadpy->dpy, Infowin->win, property, offset, | |
2230 | + length, TRUE, request_target, | |
2231 | + &xtextproperty.encoding, | |
2232 | + &xtextproperty.format, | |
2233 | + &xtextproperty.nitems, | |
2234 | + &left, | |
2235 | + &xtextproperty.value) | |
2236 | + != Success) | |
2237 | + { | |
2238 | + /* Failure */ | |
2239 | + return; | |
2240 | + } | |
2241 | + | |
2242 | + if (request_target == xa_compound_text) | |
2243 | + { | |
2244 | + char **list; | |
2245 | + int count; | |
2246 | + | |
2247 | + XmbTextPropertyToTextList(DPY, &xtextproperty, &list, &count); | |
2248 | + | |
2249 | + if (list) | |
2250 | + { | |
2251 | + int i; | |
2252 | + | |
2253 | + for (i = 0; i < count; i++) | |
2254 | + { | |
2255 | + /* Paste the text. */ | |
2256 | + err = type_string(list[i], 0); | |
2257 | + | |
2258 | + if (err) break; | |
2259 | + } | |
2260 | + | |
2261 | + /* Free the string */ | |
2262 | + XFreeStringList(list); | |
2263 | + } | |
2264 | + } | |
2265 | + else /* if (request_target == XA_STRING) */ | |
2266 | + { | |
2267 | + /* Paste the text. */ | |
2268 | + err = type_string((char *)xtextproperty.value, xtextproperty.nitems); | |
2269 | + } | |
2270 | + | |
2271 | + /* Free the data pasted. */ | |
2272 | + XFree(xtextproperty.value); | |
2273 | + | |
2274 | + /* No room. */ | |
2275 | + if (err) | |
2276 | + { | |
2277 | + plog("Paste failure (too much text selected)."); | |
2278 | + } | |
2279 | +} | |
2280 | + | |
2281 | + | |
2153 | 2282 | /* |
2154 | 2283 | * Add a character to a string in preparation for sending it to another |
2155 | 2284 | * client as a STRING. |
@@ -2157,24 +2286,17 @@ static void paste_x11_request(const Time time) | ||
2157 | 2286 | * receiving this format (although the standard specifies a restricted set). |
2158 | 2287 | * Strings do not have a colour. |
2159 | 2288 | */ |
2160 | -static int add_char_string(char *buf, byte a, char c) | |
2161 | -{ | |
2162 | - (void)a; | |
2163 | - | |
2164 | - *buf = c; | |
2165 | - return 1; | |
2166 | -} | |
2167 | - | |
2168 | -static bool paste_x11_send_text(XSelectionRequestEvent *rq, int (*add)(char *, byte, char)) | |
2289 | +static bool paste_x11_send_text(XSelectionRequestEvent *rq) | |
2169 | 2290 | { |
2170 | 2291 | char buf[1024]; |
2292 | + char *list[1000]; | |
2171 | 2293 | co_ord max, min; |
2172 | - int x,y,l; | |
2294 | + int x,y,l,n; | |
2173 | 2295 | byte a; |
2174 | 2296 | char c; |
2175 | 2297 | |
2176 | 2298 | /* Too old, or incorrect call. */ |
2177 | - if (rq->time < s_ptr->time || !add) return FALSE; | |
2299 | + if (rq->time < s_ptr->time) return FALSE; | |
2178 | 2300 | |
2179 | 2301 | /* Work out which way around to paste. */ |
2180 | 2302 | sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur); |
@@ -2189,47 +2311,102 @@ static bool paste_x11_send_text(XSelectionRequestEvent *rq, int (*add)(char *, b | ||
2189 | 2311 | /* Delete the old value of the property. */ |
2190 | 2312 | XDeleteProperty(DPY, rq->requestor, rq->property); |
2191 | 2313 | |
2192 | - for (y = 0; y < Term->hgt; y++) | |
2314 | + for (n = 0, y = 0; y < Term->hgt; y++) | |
2193 | 2315 | { |
2316 | + int kanji = 0; | |
2317 | + | |
2194 | 2318 | if (y < min.y) continue; |
2195 | 2319 | if (y > max.y) break; |
2196 | 2320 | |
2197 | - for (x = l = 0; x < Term->wid; x++) | |
2321 | + for (l = 0, x = 0; x < Term->wid; x++) | |
2198 | 2322 | { |
2199 | - if (x < min.x) continue; | |
2200 | 2323 | if (x > max.x) break; |
2201 | 2324 | |
2202 | 2325 | /* Find the character. */ |
2203 | 2326 | Term_what(x, y, &a, &c); |
2204 | 2327 | |
2328 | + if (1 == kanji) kanji = 2; | |
2329 | + else if (iskanji(c)) kanji = 1; | |
2330 | + else kanji = 0; | |
2331 | + | |
2332 | + if (x < min.x) continue; | |
2333 | + | |
2334 | + /* | |
2335 | + * A single kanji character was divided in two... | |
2336 | + * Delete the garbage. | |
2337 | + */ | |
2338 | + if ((2 == kanji && x == min.x) || | |
2339 | + (1 == kanji && x == max.x)) | |
2340 | + c = ' '; | |
2341 | + | |
2205 | 2342 | /* Add it. */ |
2206 | - l += (*add)(buf+l, a, c); | |
2343 | + buf[l] = c; | |
2344 | + l++; | |
2207 | 2345 | } |
2208 | 2346 | |
2209 | -#if 0 | |
2210 | - /* Terminate all but the last line in an appropriate way. */ | |
2211 | - if (y != max.y) l += (*add)(buf+l, TERM_WHITE, '\n'); | |
2212 | -#else | |
2213 | - /* Terminate all line unless single line message. */ | |
2214 | - if (min.y != max.y) l += (*add)(buf+l, TERM_WHITE, '\n'); | |
2215 | -#endif | |
2347 | + /* Terminate all line unless it's single line. */ | |
2348 | + if (min.y != max.y) | |
2349 | + { | |
2350 | + buf[l] = '\n'; | |
2351 | + l++; | |
2352 | + } | |
2353 | + | |
2354 | + /* End of string */ | |
2355 | + buf[l] = '\0'; | |
2216 | 2356 | |
2217 | - /* Send the (non-empty) string. */ | |
2218 | - XChangeProperty(DPY, rq->requestor, rq->property, rq->target, 8, | |
2219 | - PropModeAppend, (byte*)buf, l); | |
2357 | + list[n++] = (char *)string_make(buf); | |
2220 | 2358 | } |
2221 | - return TRUE; | |
2222 | -} | |
2223 | 2359 | |
2224 | -static Atom xa_targets, xa_timestamp; | |
2360 | + /* End of the list */ | |
2361 | + list[n] = NULL; | |
2225 | 2362 | |
2226 | -/* | |
2227 | - * Set the required variable atoms at start-up to avoid errors later. | |
2228 | - */ | |
2229 | -static void set_atoms(void) | |
2230 | -{ | |
2231 | - xa_targets = XInternAtom(DPY, "TARGETS", False); | |
2232 | - xa_timestamp = XInternAtom(DPY, "TIMESTAMP", False); | |
2363 | + | |
2364 | + if (rq->target == XA_STRING) | |
2365 | + { | |
2366 | + for (n = 0; list[n]; n++) | |
2367 | + { | |
2368 | + /* Send the (non-empty) string. */ | |
2369 | + XChangeProperty(DPY, rq->requestor, rq->property, rq->target, 8, | |
2370 | + PropModeAppend, (unsigned char *)list[n], strlen(list[n])); | |
2371 | + } | |
2372 | + } | |
2373 | + | |
2374 | + else if (rq->target == xa_text || | |
2375 | + rq->target == xa_compound_text) | |
2376 | + { | |
2377 | + XTextProperty text_prop; | |
2378 | + XICCEncodingStyle style; | |
2379 | + | |
2380 | + if (rq->target == xa_text) | |
2381 | + style = XStdICCTextStyle; | |
2382 | + else /* if (rq->target == xa_compound_text) */ | |
2383 | + style = XCompoundTextStyle; | |
2384 | + | |
2385 | + if (Success == | |
2386 | + XmbTextListToTextProperty(DPY, list, n, style, &text_prop)) | |
2387 | + { | |
2388 | + /* Send the compound text */ | |
2389 | + XChangeProperty(DPY, | |
2390 | + rq->requestor, | |
2391 | + rq->property, | |
2392 | + text_prop.encoding, | |
2393 | + text_prop.format, | |
2394 | + PropModeAppend, | |
2395 | + text_prop.value, | |
2396 | + text_prop.nitems); | |
2397 | + | |
2398 | + /* Free the data. */ | |
2399 | + XFree(text_prop.value); | |
2400 | + } | |
2401 | + } | |
2402 | + | |
2403 | + /* Free the list of strings */ | |
2404 | + for (n = 0; list[n]; n++) | |
2405 | + { | |
2406 | + string_free(list[n]); | |
2407 | + } | |
2408 | + | |
2409 | + return TRUE; | |
2233 | 2410 | } |
2234 | 2411 | |
2235 | 2412 | /* |
@@ -2253,16 +2430,20 @@ static void paste_x11_send(XSelectionRequestEvent *rq) | ||
2253 | 2430 | * Note that this currently rejects MULTIPLE targets. |
2254 | 2431 | */ |
2255 | 2432 | |
2256 | - if (rq->target == XA_STRING) | |
2433 | + if (rq->target == XA_STRING || | |
2434 | + rq->target == xa_text || | |
2435 | + rq->target == xa_compound_text) | |
2257 | 2436 | { |
2258 | - if (!paste_x11_send_text(rq, add_char_string)) | |
2437 | + if (!paste_x11_send_text(rq)) | |
2259 | 2438 | ptr->property = None; |
2260 | 2439 | } |
2261 | 2440 | else if (rq->target == xa_targets) |
2262 | 2441 | { |
2263 | - Atom target_list[2]; | |
2442 | + Atom target_list[4]; | |
2264 | 2443 | target_list[0] = XA_STRING; |
2265 | - target_list[1] = xa_targets; | |
2444 | + target_list[1] = xa_text; | |
2445 | + target_list[2] = xa_compound_text; | |
2446 | + target_list[3] = xa_targets; | |
2266 | 2447 | XChangeProperty(DPY, rq->requestor, rq->property, rq->target, |
2267 | 2448 | (8 * sizeof(target_list[0])), PropModeReplace, |
2268 | 2449 | (unsigned char *)target_list, |
@@ -2283,76 +2464,6 @@ static void paste_x11_send(XSelectionRequestEvent *rq) | ||
2283 | 2464 | XSendEvent(DPY, rq->requestor, FALSE, NoEventMask, &event); |
2284 | 2465 | } |
2285 | 2466 | |
2286 | -/* | |
2287 | - * Add the contents of the PRIMARY buffer to the input queue. | |
2288 | - * | |
2289 | - * Hack - This doesn't use the "time" of the event, and so accepts anything a | |
2290 | - * client tries to send it. | |
2291 | - */ | |
2292 | -static void paste_x11_accept(const XSelectionEvent *ptr) | |
2293 | -{ | |
2294 | - unsigned long offset, left; | |
2295 | - | |
2296 | - /* Failure. */ | |
2297 | - if (ptr->property == None) | |
2298 | - { | |
2299 | - /* bell("Paste failure (remote client could not send)."); */ | |
2300 | - return; | |
2301 | - } | |
2302 | - | |
2303 | - if (ptr->selection != XA_PRIMARY) | |
2304 | - { | |
2305 | - /* bell("Paste failure (remote client did not send primary selection)."); */ | |
2306 | - return; | |
2307 | - } | |
2308 | - | |
2309 | - if (ptr->target != XA_STRING) | |
2310 | - { | |
2311 | - /* bell("Paste failure (selection in unknown format)."); */ | |
2312 | - return; | |
2313 | - } | |
2314 | - | |
2315 | - for (offset = 0; ; offset += left) | |
2316 | - { | |
2317 | - errr err; | |
2318 | - | |
2319 | - /* A pointer for the pasted information. */ | |
2320 | - unsigned char *data; | |
2321 | - | |
2322 | - Atom type; | |
2323 | - int fmt; | |
2324 | - unsigned long nitems; | |
2325 | - | |
2326 | - /* Set data to the string, and catch errors. */ | |
2327 | - if (XGetWindowProperty(Metadpy->dpy, Infowin->win, XA_STRING, offset, | |
2328 | - 32767, TRUE, XA_STRING, &type, &fmt, &nitems, &left, &data) | |
2329 | - != Success) break; | |
2330 | - | |
2331 | - /* Paste the text. */ | |
2332 | - err = type_string((char*)data, nitems); | |
2333 | - | |
2334 | - /* Free the data pasted. */ | |
2335 | - XFree(data); | |
2336 | - | |
2337 | - /* No room. */ | |
2338 | - if (err == PARSE_ERROR_OUT_OF_MEMORY) | |
2339 | - { | |
2340 | - /* bell("Paste failure (too much text selected)."); */ | |
2341 | - break; | |
2342 | - } | |
2343 | - /* Paranoia? - strange errors. */ | |
2344 | - else if (err) | |
2345 | - { | |
2346 | - break; | |
2347 | - } | |
2348 | - | |
2349 | - /* Pasted everything. */ | |
2350 | - if (!left) return; | |
2351 | - } | |
2352 | - | |
2353 | - /* An error has occurred, so free the last bit of data before returning. */ | |
2354 | - XFree(data); | |
2355 | -} | |
2356 | 2467 | |
2357 | 2468 | /* |
2358 | 2469 | * Handle various events conditional on presses of a mouse button. |
@@ -2365,7 +2476,7 @@ static void handle_button(Time time, int x, int y, int button, | ||
2365 | 2476 | |
2366 | 2477 | if (press && button == 1) copy_x11_start(x, y); |
2367 | 2478 | if (!press && button == 1) copy_x11_end(time); |
2368 | - if (!press && button == 2) paste_x11_request(time); | |
2479 | + if (!press && button == 2) paste_x11_request(xa_compound_text, time); | |
2369 | 2480 | } |
2370 | 2481 | |
2371 | 2482 |