1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
19
20 21 22 23
24
25
26
27
28 #ifdef MSDOS
29
30 #include <config.h>
31 #include <string.h>
32 #include <dpmi.h>
33 #include <go32.h>
34 #include <sys/farptr.h>
35 #include <setjmp.h>
36 #include "lisp.h"
37 #include "dispextern.h"
38 #include "frame.h"
39 #include "blockinput.h"
40 #include "buffer.h"
41 #include "character.h"
42 #include "coding.h"
43 #include "composite.h"
44
45 46 47
48
49 #define CF_TEXT 0x01
50 #define CF_BITMAP 0x02
51 #define CF_METAFILE 0x03
52 #define CF_SYLK 0x04
53 #define CF_DIF 0x05
54 #define CF_TIFF 0x06
55 #define CF_OEMTEXT 0x07
56 #define CF_DIBBITMAP 0x08
57 #define CF_WINWRITE 0x80
58 #define CF_DSPTEXT 0x81
59 #define CF_DSPBITMAP 0x82
60
61 unsigned identify_winoldap_version (void);
62 unsigned open_clipboard (void);
63 unsigned empty_clipboard (void);
64 unsigned set_clipboard_data (unsigned, void *, unsigned, int);
65 unsigned get_clipboard_data_size (unsigned);
66 unsigned get_clipboard_data (unsigned, void *, unsigned, int);
67 unsigned close_clipboard (void);
68 unsigned clipboard_compact (unsigned);
69
70 Lisp_Object QCLIPBOARD, QPRIMARY;
71
72 73
74 static Lisp_Object Vselection_coding_system;
75
76
77 static Lisp_Object Vnext_selection_coding_system;
78
79 80
81 static struct {
82 unsigned long size;
83 unsigned short rm_segment;
84 } clipboard_xfer_buf_info;
85
86 87 88 89 90 91
92 static unsigned char *last_clipboard_text;
93
94
95 static size_t clipboard_storage_size;
96
97 98 99 100 101
102
103 104 105 106 107 108
109
110
111 unsigned
112 identify_winoldap_version ()
113 {
114 __dpmi_regs regs;
115
116 117 118 119
120 regs.x.ax = 0x1700;
121 __dpmi_int(0x2f, ®s);
122 return regs.x.ax;
123 }
124
125
126 unsigned
127 open_clipboard ()
128 {
129 __dpmi_regs regs;
130
131
132 133 134 135 136
137 if (identify_winoldap_version () == 0x1700)
138 return 0;
139
140 141 142
143 regs.x.ax = 0x1701;
144 __dpmi_int(0x2f, ®s);
145 return regs.x.ax;
146 }
147
148
149 unsigned
150 empty_clipboard ()
151 {
152 __dpmi_regs regs;
153
154 155 156
157 regs.x.ax = 0x1702;
158 __dpmi_int(0x2f, ®s);
159 return regs.x.ax;
160 }
161
162 163
164 static unsigned long
165 alloc_xfer_buf (want_size)
166 unsigned want_size;
167 {
168 __dpmi_regs regs;
169
170
171 if (want_size <= _go32_info_block.size_of_transfer_buffer)
172 return __tb & 0xfffff;
173
174 175
176 if (want_size > 0xfffff)
177 return 0;
178
179 180
181 clipboard_xfer_buf_info.size = (want_size + 15) >> 4;
182
183 184
185 regs.h.ah = 0x48;
186 regs.x.bx = clipboard_xfer_buf_info.size;
187 __dpmi_int (0x21, ®s);
188 if (regs.x.flags & 1)
189 {
190 clipboard_xfer_buf_info.size = 0;
191 return 0;
192 }
193
194 clipboard_xfer_buf_info.rm_segment = regs.x.ax;
195 return (((int)clipboard_xfer_buf_info.rm_segment) << 4) & 0xfffff;
196 }
197
198 199 200 201
202 static void
203 free_xfer_buf ()
204 {
205
206 if (clipboard_xfer_buf_info.size)
207 {
208 __dpmi_regs regs;
209
210 211
212 regs.h.ah = 0x49;
213 regs.x.es = clipboard_xfer_buf_info.rm_segment;
214 __dpmi_int (0x21, ®s);
215 clipboard_xfer_buf_info.size = 0;
216 }
217 }
218
219
220 unsigned
221 set_clipboard_data (Format, Data, Size, Raw)
222 unsigned Format;
223 void *Data;
224 unsigned Size;
225 int Raw;
226 {
227 __dpmi_regs regs;
228 unsigned truelen;
229 unsigned long xbuf_addr, buf_offset;
230 unsigned char *dp = Data, *dstart = dp;
231
232 if (Format != CF_OEMTEXT)
233 return 3;
234
235 236 237
238 truelen = Size + 1;
239
240 if (!Raw)
241 {
242
243 while ((dp = memchr (dp, '\n', Size - (dp - dstart))) != 0)
244 {
245 truelen++;
246 dp++;
247 }
248 }
249
250 if (clipboard_compact (truelen) < truelen)
251 return 1;
252
253 if ((xbuf_addr = alloc_xfer_buf (truelen)) == 0)
254 return 1;
255
256
257 if (Raw)
258 {
259 dosmemput (Data, Size, xbuf_addr);
260
261 262
263 _farpokeb (_dos_ds, xbuf_addr + Size, '\0');
264 }
265 else
266 {
267 dp = Data;
268 buf_offset = xbuf_addr;
269 _farsetsel (_dos_ds);
270 while (Size--)
271 {
272 273
274 if (*dp == '\0')
275 return 2;
276 if (*dp == '\n')
277 _farnspokeb (buf_offset++, '\r');
278 _farnspokeb (buf_offset++, *dp++);
279 }
280
281 282
283 _farnspokeb (buf_offset, '\0');
284 }
285
286 287 288
289 if (clipboard_storage_size < truelen)
290 {
291 clipboard_storage_size = truelen + 100;
292 last_clipboard_text =
293 (char *) xrealloc (last_clipboard_text, clipboard_storage_size);
294 }
295 if (last_clipboard_text)
296 dosmemget (xbuf_addr, truelen, last_clipboard_text);
297
298 299 300 301 302 303
304 regs.x.ax = 0x1703;
305 regs.x.dx = Format;
306 regs.x.si = truelen >> 16;
307 regs.x.cx = truelen & 0xffff;
308 regs.x.es = xbuf_addr >> 4;
309 regs.x.bx = xbuf_addr & 15;
310 __dpmi_int(0x2f, ®s);
311
312 free_xfer_buf ();
313
314
315 if (regs.x.ax == 0)
316 *last_clipboard_text = '\0';
317
318
319 return regs.x.ax > 0 ? 0 : 3;
320 }
321
322
323 unsigned
324 get_clipboard_data_size (Format)
325 unsigned Format;
326 {
327 __dpmi_regs regs;
328
329 330 331 332 333 334
335 regs.x.ax = 0x1704;
336 regs.x.dx = Format;
337 __dpmi_int(0x2f, ®s);
338 return ( (((unsigned)regs.x.dx) << 16) | regs.x.ax);
339 }
340
341 342 343
344 unsigned
345 get_clipboard_data (Format, Data, Size, Raw)
346 unsigned Format;
347 void *Data;
348 unsigned Size;
349 int Raw;
350 {
351 __dpmi_regs regs;
352 unsigned long xbuf_addr;
353 unsigned char *dp = Data;
354
355 if (Format != CF_OEMTEXT)
356 return 0;
357
358 if (Size == 0)
359 return 0;
360
361 if ((xbuf_addr = alloc_xfer_buf (Size)) == 0)
362 return 0;
363
364 365 366 367 368 369
370 regs.x.ax = 0x1705;
371 regs.x.dx = Format;
372 regs.x.es = xbuf_addr >> 4;
373 regs.x.bx = xbuf_addr & 15;
374 __dpmi_int(0x2f, ®s);
375 if (regs.x.ax != 0)
376 {
377 unsigned char null_char = '\0';
378 unsigned long xbuf_beg = xbuf_addr;
379
380 381
382 register unsigned char *lcdp =
383 last_clipboard_text == NULL ? &null_char : last_clipboard_text;
384
385 386
387 _farsetsel (_dos_ds);
388 while (Size--)
389 {
390 register unsigned char c = _farnspeekb (xbuf_addr++);
391
392 if (*lcdp == c)
393 lcdp++;
394
395 if ((*dp++ = c) == '\r' && !Raw && _farnspeekb (xbuf_addr) == '\n')
396 {
397 dp--;
398 *dp++ = '\n';
399 xbuf_addr++;
400 if (*lcdp == '\n')
401 lcdp++;
402 }
403 404 405 406
407 else if (c == '\0')
408 break;
409 }
410
411 412 413 414 415
416 if (last_clipboard_text &&
417 xbuf_addr - xbuf_beg == (long)(lcdp - last_clipboard_text))
418 dp = (unsigned char *)Data + 1;
419 }
420
421 free_xfer_buf ();
422
423 return (unsigned) (dp - (unsigned char *)Data - 1);
424 }
425
426
427 unsigned
428 close_clipboard ()
429 {
430 __dpmi_regs regs;
431
432 433 434
435 regs.x.ax = 0x1708;
436 __dpmi_int(0x2f, ®s);
437 return regs.x.ax;
438 }
439
440
441 unsigned
442 clipboard_compact (Size)
443 unsigned Size;
444 {
445 __dpmi_regs regs;
446
447 448 449 450
451 regs.x.ax = 0x1709;
452 regs.x.si = Size >> 16;
453 regs.x.cx = Size & 0xffff;
454 __dpmi_int(0x2f, ®s);
455 return ((unsigned)regs.x.dx << 16) | regs.x.ax;
456 }
457
458 static char no_mem_msg[] =
459 "(Not enough DOS memory to put saved text into clipboard.)";
460 static char binary_msg[] =
461 "(Binary characters in saved text; clipboard data not set.)";
462 static char system_error_msg[] =
463 "(Clipboard interface failure; clipboard data not set.)";
464
465 DEFUN ("w16-set-clipboard-data", Fw16_set_clipboard_data, Sw16_set_clipboard_data, 1, 2, 0,
466 doc: )
467 (string, frame)
468 Lisp_Object string, frame;
469 {
470 unsigned ok = 1, put_status = 0;
471 int nbytes, charset_info, no_crlf_conversion;
472 unsigned char *src, *dst = NULL;
473
474 CHECK_STRING (string);
475
476 if (NILP (frame))
477 frame = Fselected_frame ();
478
479 CHECK_LIVE_FRAME (frame);
480 if ( !FRAME_MSDOS_P (XFRAME (frame)))
481 goto done;
482
483 BLOCK_INPUT;
484
485 if (!open_clipboard ())
486 goto error;
487
488 nbytes = SBYTES (string);
489 src = SDATA (string);
490
491
492 for (dst = src; dst < src + nbytes; dst++)
493 {
494 if (*dst == '\0' || *dst >= 0x80)
495 break;
496 }
497 if (dst >= src + nbytes)
498 {
499 500
501 no_crlf_conversion = 0;
502 Vlast_coding_system_used = Qraw_text;
503 dst = NULL;
504 }
505 else
506 {
507 508
509 int bufsize;
510 struct coding_system coding;
511 unsigned char *htext2;
512 Lisp_Object coding_system =
513 NILP (Vnext_selection_coding_system) ?
514 Vselection_coding_system : Vnext_selection_coding_system;
515
516 setup_coding_system (Fcheck_coding_system (coding_system), &coding);
517 coding.dst_bytes = nbytes * 4;
518 coding.destination = (unsigned char *) xmalloc (coding.dst_bytes);
519 Vnext_selection_coding_system = Qnil;
520 coding.mode |= CODING_MODE_LAST_BLOCK;
521 dst = coding.destination;
522 encode_coding_object (&coding, string, 0, 0,
523 SCHARS (string), nbytes, Qnil);
524 no_crlf_conversion = 1;
525 nbytes = coding.produced;
526 Vlast_coding_system_used = CODING_ID_NAME (coding.id);
527 src = dst;
528 }
529
530 ok = empty_clipboard ()
531 && ((put_status
532 = set_clipboard_data (CF_OEMTEXT, src, nbytes, no_crlf_conversion))
533 == 0);
534
535 if (!no_crlf_conversion)
536 close_clipboard ();
537
538 if (ok) goto unblock;
539
540 error:
541
542 ok = 0;
543
544 unblock:
545 xfree (dst);
546 UNBLOCK_INPUT;
547
548 549 550 551 552
553 if (put_status)
554 {
555 switch (put_status)
556 {
557 case 1:
558 message2 (no_mem_msg, sizeof (no_mem_msg) - 1, 0);
559 break;
560 case 2:
561 message2 (binary_msg, sizeof (binary_msg) - 1, 0);
562 break;
563 case 3:
564 message2 (system_error_msg, sizeof (system_error_msg) - 1, 0);
565 break;
566 }
567 sit_for (make_number (2), 0, 2);
568 }
569
570 done:
571
572 return (ok && put_status == 0 ? string : Qnil);
573 }
574
575 DEFUN ("w16-get-clipboard-data", Fw16_get_clipboard_data, Sw16_get_clipboard_data, 0, 1, 0,
576 doc: )
577 (frame)
578 Lisp_Object frame;
579 {
580 unsigned data_size, truelen;
581 unsigned char *htext = NULL;
582 Lisp_Object ret = Qnil;
583 int no_crlf_conversion, require_decoding = 0;
584
585 if (NILP (frame))
586 frame = Fselected_frame ();
587
588 CHECK_LIVE_FRAME (frame);
589 if ( !FRAME_MSDOS_P (XFRAME (frame)))
590 goto done;
591
592 BLOCK_INPUT;
593
594 if (!open_clipboard ())
595 goto unblock;
596
597 if ((data_size = get_clipboard_data_size (CF_OEMTEXT)) == 0 ||
598 (htext = (unsigned char *)xmalloc (data_size)) == 0)
599 goto closeclip;
600
601 602 603
604 if ((truelen = get_clipboard_data (CF_OEMTEXT, htext, data_size, 0)) == 0)
605 goto closeclip;
606
607
608 {
609 610
611 int i;
612
613 for (i = 0; i < truelen; i++)
614 {
615 if (htext[i] >= 0x80)
616 {
617 require_decoding = 1;
618 break;
619 }
620 }
621 }
622 if (require_decoding)
623 {
624 int bufsize;
625 unsigned char *buf;
626 struct coding_system coding;
627 Lisp_Object coding_system = Vnext_selection_coding_system;
628
629 truelen = get_clipboard_data (CF_OEMTEXT, htext, data_size, 1);
630 if (NILP (coding_system))
631 coding_system = Vselection_coding_system;
632 setup_coding_system (Fcheck_coding_system (coding_system), &coding);
633 coding.source = htext;
634 coding.mode |= CODING_MODE_LAST_BLOCK;
635 636
637 coding.mode &= CODING_ANNOTATION_MASK;
638 decode_coding_object (&coding, Qnil, 0, 0, truelen, truelen, Qt);
639 ret = coding.dst_object;
640 Vlast_coding_system_used = CODING_ID_NAME (coding.id);
641 }
642 else
643 {
644 ret = make_unibyte_string ((char *) htext, truelen);
645 Vlast_coding_system_used = Qraw_text;
646 }
647
648 xfree (htext);
649 Vnext_selection_coding_system = Qnil;
650
651 closeclip:
652 close_clipboard ();
653
654 unblock:
655 UNBLOCK_INPUT;
656
657 done:
658
659 return (ret);
660 }
661
662
663
664 DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
665 0, 1, 0,
666 doc: 667 668 669 670 671 )
672 (selection)
673 Lisp_Object selection;
674 {
675 CHECK_SYMBOL (selection);
676
677 678 679 680 681 682 683 684 685 686
687 if ((EQ (selection, Qnil) || EQ (selection, QPRIMARY))
688 && ! NILP (Fsymbol_value (Fintern_soft (build_string ("kill-ring"),
689 Qnil))))
690 return Qt;
691
692 if (EQ (selection, QCLIPBOARD))
693 {
694 Lisp_Object val = Qnil;
695
696 if (open_clipboard ())
697 {
698 if (get_clipboard_data_size (CF_OEMTEXT))
699 val = Qt;
700 close_clipboard ();
701 }
702 return val;
703 }
704 return Qnil;
705 }
706
707 void
708 syms_of_win16select ()
709 {
710 defsubr (&Sw16_set_clipboard_data);
711 defsubr (&Sw16_get_clipboard_data);
712 defsubr (&Sx_selection_exists_p);
713
714 DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system,
715 doc: 716 717 718 );
719 Vselection_coding_system = intern ("iso-latin-1-dos");
720
721 DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system,
722 doc: 723 724 725 726 );
727 Vnext_selection_coding_system = Qnil;
728
729 QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY);
730 QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
731 }
732
733 #endif
734
735 736