Skip to content

Commit b35117a

Browse files
committed
FEAT: macOS basic clipboard port implementation
1 parent dbe8aa5 commit b35117a

File tree

4 files changed

+246
-11
lines changed

4 files changed

+246
-11
lines changed

make/rebol3.nest

+8
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,14 @@ include-clipboard: [
368368
core-files: %core/p-clipboard.c
369369
host-files: %os/win32/dev-clipboard.c
370370
]
371+
#if macOS? [
372+
config: INCLUDE_CLIPBOARD
373+
core-files: %core/p-clipboard.c
374+
host-files: %os/osx/dev-clipboard.c
375+
host-files: %os/osx/sys-clipboard.m
376+
host-files: %os/osx/sys-utils.m
377+
framework: AppKit
378+
]
371379
]
372380
include-midi: [
373381
#if Windows? [

src/core/p-clipboard.c

+26-11
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@
3939
REBREQ *req;
4040
REBINT result;
4141
REBVAL *arg;
42-
REBCNT args = 0;
43-
REBCNT refs; // refinement argument flags
42+
REBCNT refs = 0; // refinement argument flags
4443
REBINT len;
4544
REBSER *ser;
4645

@@ -71,11 +70,19 @@
7170
return R_NONE;
7271

7372
case A_READ:
74-
args = Find_Refines(ds, ALL_READ_REFS);
73+
refs = Find_Refines(ds, ALL_READ_REFS);
7574
// This device is opened on the READ:
7675
if (!IS_OPEN(req)) {
7776
if (OS_DO_DEVICE(req, RDC_OPEN)) Trap_Port(RE_CANNOT_OPEN, port, req->error);
7877
}
78+
79+
// Handle /part refinement:
80+
if (refs & AM_READ_PART) {
81+
req->length = VAL_INT32(D_ARG(ARG_READ_LENGTH));
82+
} else {
83+
req->length = 0;
84+
}
85+
7986
// Issue the read request:
8087
CLR_FLAG(req->flags, RRF_WIDE); // allow byte or wide chars
8188
result = OS_DO_DEVICE(req, RDC_READ);
@@ -96,7 +103,7 @@
96103
OS_FREE(req->data); // release the copy buffer
97104
req->data = 0;
98105

99-
if (args & AM_READ_LINES) {
106+
if (refs & AM_READ_LINES) {
100107
Set_Block(D_RET, Split_Lines(arg));
101108
} else {
102109
*D_RET = *arg;
@@ -126,14 +133,16 @@
126133
if (refs & AM_WRITE_PART && VAL_INT32(D_ARG(ARG_WRITE_LENGTH)) < len)
127134
len = VAL_INT32(D_ARG(ARG_WRITE_LENGTH));
128135

136+
#ifdef TO_WINDOWS
137+
// Oldes: this code is very old and should be revisited!!!
129138
// If bytes, see if we can fit it:
130139
if (SERIES_WIDE(VAL_SERIES(arg)) == 1) {
131-
#ifdef ARG_STRINGS_ALLOWED
132-
if (Is_Not_ASCII(VAL_BIN_DATA(arg), len)) {
133-
Set_String(arg, Copy_Bytes_To_Unicode(VAL_BIN_DATA(arg), len));
134-
} else
135-
req->data = VAL_BIN_DATA(arg);
136-
#endif
140+
#ifdef ARG_STRINGS_ALLOWED
141+
if (Is_Not_ASCII(VAL_BIN_DATA(arg), len)) {
142+
Set_String(arg, Copy_Bytes_To_Unicode(VAL_BIN_DATA(arg), len));
143+
} else
144+
req->data = VAL_BIN_DATA(arg);
145+
#endif
137146

138147
// Temp conversion:!!!
139148
ser = Make_Unicode(len);
@@ -153,7 +162,13 @@
153162

154163
// Temp!!!
155164
req->length = len * sizeof(REBUNI);
156-
165+
166+
#else // macOS requires UTF8 encoded data (no clipboard support on other oses yet)
167+
ser = Encode_UTF8_Value(arg, len, 0);
168+
Set_String(arg, ser);
169+
req->data = VAL_BIN_DATA(arg);
170+
req->length = len;
171+
#endif
157172
// Setup the write:
158173
*OFV(port, STD_PORT_DATA) = *arg; // keep it GC safe
159174
req->actual = 0;

src/os/osx/dev-clipboard.c

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/***********************************************************************
2+
**
3+
** REBOL [R3] Language Interpreter and Run-time Environment
4+
**
5+
** Copyright 2012 REBOL Technologies
6+
** REBOL is a trademark of REBOL Technologies
7+
**
8+
** Licensed under the Apache License, Version 2.0 (the "License");
9+
** you may not use this file except in compliance with the License.
10+
** You may obtain a copy of the License at
11+
**
12+
** http://www.apache.org/licenses/LICENSE-2.0
13+
**
14+
** Unless required by applicable law or agreed to in writing, software
15+
** distributed under the License is distributed on an "AS IS" BASIS,
16+
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
** See the License for the specific language governing permissions and
18+
** limitations under the License.
19+
**
20+
************************************************************************
21+
**
22+
** Title: Device: Clipboard access for Win32
23+
** Author: Carl Sassenrath, Oldes
24+
** Purpose:
25+
** Provides a very simple interface to the clipboard for text.
26+
** May be expanded in the future for images, etc.
27+
**
28+
************************************************************************
29+
**
30+
** NOTE to PROGRAMMERS:
31+
**
32+
** 1. Keep code clear and simple.
33+
** 2. Document unusual code, reasoning, or gotchas.
34+
** 3. Use same style for code, vars, indent(4), comments, etc.
35+
** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs.
36+
** 5. Test everything, then test it again.
37+
**
38+
***********************************************************************/
39+
40+
#include <stdio.h>
41+
42+
#include "sys-net.h"
43+
#include "reb-host.h"
44+
#include "host-lib.h"
45+
46+
47+
REBOOL GetClipboardStringData(REBREQ *req);
48+
REBOOL SetClipboardStringData(REBREQ *req);
49+
50+
/***********************************************************************
51+
**
52+
*/ DEVICE_CMD Open_Clipboard(REBREQ *req)
53+
/*
54+
***********************************************************************/
55+
{
56+
SET_OPEN(req);
57+
return DR_DONE;
58+
}
59+
60+
/***********************************************************************
61+
**
62+
*/ DEVICE_CMD Close_Clipboard(REBREQ *req)
63+
/*
64+
***********************************************************************/
65+
{
66+
SET_CLOSED(req);
67+
return DR_DONE;
68+
}
69+
70+
71+
/***********************************************************************
72+
**
73+
*/ DEVICE_CMD Read_Clipboard(REBREQ *req)
74+
/*
75+
***********************************************************************/
76+
{
77+
req->actual = 0;
78+
79+
if(!GetClipboardStringData(req)){
80+
req->error = 20;
81+
// just a random number... would be better to have some system for it
82+
return DR_ERROR;
83+
}
84+
85+
return DR_DONE;
86+
}
87+
88+
89+
/***********************************************************************
90+
**
91+
*/ DEVICE_CMD Write_Clipboard(REBREQ *req)
92+
/*
93+
** Expects data in UTF8 encoding in req->data!
94+
**
95+
***********************************************************************/
96+
{
97+
if(!SetClipboardStringData(req)) {
98+
req->error = 20;
99+
// just a random number... would be better to have some system for it
100+
return DR_ERROR;
101+
}
102+
return DR_DONE;
103+
}
104+
105+
106+
/***********************************************************************
107+
**
108+
*/ DEVICE_CMD Poll_Clipboard(REBREQ *req)
109+
/*
110+
***********************************************************************/
111+
{
112+
return DR_DONE;
113+
}
114+
115+
116+
/***********************************************************************
117+
**
118+
** Command Dispatch Table (RDC_ enum order)
119+
**
120+
***********************************************************************/
121+
122+
static DEVICE_CMD_FUNC Dev_Cmds[RDC_MAX] =
123+
{
124+
0,
125+
0,
126+
Open_Clipboard,
127+
Close_Clipboard,
128+
Read_Clipboard,
129+
Write_Clipboard,
130+
Poll_Clipboard,
131+
};
132+
133+
DEFINE_DEV(Dev_Clipboard, "Clipboard", 1, Dev_Cmds, RDC_MAX, 0);

src/os/osx/sys-clipboard.m

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/***********************************************************************
2+
**
3+
** REBOL [R3] Language Interpreter and Run-time Environment
4+
**
5+
** Copyright 2021 Oldes
6+
**
7+
** Licensed under the Apache License, Version 2.0 (the "License");
8+
** you may not use this file except in compliance with the License.
9+
** You may obtain a copy of the License at
10+
**
11+
** http://www.apache.org/licenses/LICENSE-2.0
12+
**
13+
** Unless required by applicable law or agreed to in writing, software
14+
** distributed under the License is distributed on an "AS IS" BASIS,
15+
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
** See the License for the specific language governing permissions and
17+
** limitations under the License.
18+
**
19+
************************************************************************
20+
**
21+
** Title: Device: Clipboard access for macOS
22+
** Author: Oldes
23+
** Purpose:
24+
** Provides a very simple interface to the clipboard for text.
25+
** May be expanded in the future for images, etc.
26+
**
27+
************************************************************************/
28+
29+
#include <AppKit/AppKit.h>
30+
#include "reb-host.h"
31+
#include "host-lib.h" // for OS_Make
32+
33+
void EmptyClipboard(void){
34+
[[NSPasteboard generalPasteboard] clearContents];
35+
}
36+
37+
REBOOL GetClipboardStringData(REBREQ *req){
38+
unsigned long len;
39+
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
40+
NSArray *classes=[NSArray arrayWithObject:[NSString class]];
41+
NSDictionary *options=[NSDictionary dictionary];
42+
NSArray *clipboardContent=[pasteboard readObjectsForClasses:classes options:options];
43+
44+
if(clipboardContent)
45+
{
46+
if(0<[clipboardContent count])
47+
{
48+
NSString *str=[clipboardContent objectAtIndex:0];
49+
if(NULL!=str)
50+
{
51+
len = strlen([str UTF8String]);
52+
// req->length is used when reading just part of the result
53+
if (req->length > 0 && req->length < len)
54+
len = req->length;
55+
56+
req->data = (REBYTE*)OS_Make(len+1);
57+
req->actual = len;
58+
COPY_STR(req->data, [str UTF8String], len);
59+
return TRUE;
60+
}
61+
}
62+
}
63+
return FALSE;
64+
}
65+
66+
REBOOL SetClipboardStringData(REBREQ *req){
67+
const char *str = cs_cast(req->data);
68+
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
69+
[pasteboard clearContents];
70+
71+
NSString *nsstr = [NSString stringWithUTF8String:str];
72+
73+
if (!nsstr) return FALSE;
74+
NSArray *arr = [NSArray arrayWithObject:[NSString stringWithUTF8String:str]];
75+
BOOL res = [pasteboard writeObjects:arr];
76+
req->actual = req->length;
77+
78+
return res;
79+
}

0 commit comments

Comments
 (0)