Skip to content

Commit

Permalink
FEAT: macOS basic clipboard port implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Oldes committed Aug 25, 2021
1 parent dbe8aa5 commit b35117a
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 11 deletions.
8 changes: 8 additions & 0 deletions make/rebol3.nest
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,14 @@ include-clipboard: [
core-files: %core/p-clipboard.c
host-files: %os/win32/dev-clipboard.c
]
#if macOS? [
config: INCLUDE_CLIPBOARD
core-files: %core/p-clipboard.c
host-files: %os/osx/dev-clipboard.c
host-files: %os/osx/sys-clipboard.m
host-files: %os/osx/sys-utils.m
framework: AppKit
]
]
include-midi: [
#if Windows? [
Expand Down
37 changes: 26 additions & 11 deletions src/core/p-clipboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@
REBREQ *req;
REBINT result;
REBVAL *arg;
REBCNT args = 0;
REBCNT refs; // refinement argument flags
REBCNT refs = 0; // refinement argument flags
REBINT len;
REBSER *ser;

Expand Down Expand Up @@ -71,11 +70,19 @@
return R_NONE;

case A_READ:
args = Find_Refines(ds, ALL_READ_REFS);
refs = Find_Refines(ds, ALL_READ_REFS);
// This device is opened on the READ:
if (!IS_OPEN(req)) {
if (OS_DO_DEVICE(req, RDC_OPEN)) Trap_Port(RE_CANNOT_OPEN, port, req->error);
}

// Handle /part refinement:
if (refs & AM_READ_PART) {
req->length = VAL_INT32(D_ARG(ARG_READ_LENGTH));
} else {
req->length = 0;
}

// Issue the read request:
CLR_FLAG(req->flags, RRF_WIDE); // allow byte or wide chars
result = OS_DO_DEVICE(req, RDC_READ);
Expand All @@ -96,7 +103,7 @@
OS_FREE(req->data); // release the copy buffer
req->data = 0;

if (args & AM_READ_LINES) {
if (refs & AM_READ_LINES) {
Set_Block(D_RET, Split_Lines(arg));
} else {
*D_RET = *arg;
Expand Down Expand Up @@ -126,14 +133,16 @@
if (refs & AM_WRITE_PART && VAL_INT32(D_ARG(ARG_WRITE_LENGTH)) < len)
len = VAL_INT32(D_ARG(ARG_WRITE_LENGTH));

#ifdef TO_WINDOWS
// Oldes: this code is very old and should be revisited!!!
// If bytes, see if we can fit it:
if (SERIES_WIDE(VAL_SERIES(arg)) == 1) {
#ifdef ARG_STRINGS_ALLOWED
if (Is_Not_ASCII(VAL_BIN_DATA(arg), len)) {
Set_String(arg, Copy_Bytes_To_Unicode(VAL_BIN_DATA(arg), len));
} else
req->data = VAL_BIN_DATA(arg);
#endif
#ifdef ARG_STRINGS_ALLOWED
if (Is_Not_ASCII(VAL_BIN_DATA(arg), len)) {
Set_String(arg, Copy_Bytes_To_Unicode(VAL_BIN_DATA(arg), len));
} else
req->data = VAL_BIN_DATA(arg);
#endif

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

// Temp!!!
req->length = len * sizeof(REBUNI);


#else // macOS requires UTF8 encoded data (no clipboard support on other oses yet)
ser = Encode_UTF8_Value(arg, len, 0);
Set_String(arg, ser);
req->data = VAL_BIN_DATA(arg);
req->length = len;
#endif
// Setup the write:
*OFV(port, STD_PORT_DATA) = *arg; // keep it GC safe
req->actual = 0;
Expand Down
133 changes: 133 additions & 0 deletions src/os/osx/dev-clipboard.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/***********************************************************************
**
** REBOL [R3] Language Interpreter and Run-time Environment
**
** Copyright 2012 REBOL Technologies
** REBOL is a trademark of REBOL Technologies
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
**
************************************************************************
**
** Title: Device: Clipboard access for Win32
** Author: Carl Sassenrath, Oldes
** Purpose:
** Provides a very simple interface to the clipboard for text.
** May be expanded in the future for images, etc.
**
************************************************************************
**
** NOTE to PROGRAMMERS:
**
** 1. Keep code clear and simple.
** 2. Document unusual code, reasoning, or gotchas.
** 3. Use same style for code, vars, indent(4), comments, etc.
** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs.
** 5. Test everything, then test it again.
**
***********************************************************************/

#include <stdio.h>

#include "sys-net.h"
#include "reb-host.h"
#include "host-lib.h"


REBOOL GetClipboardStringData(REBREQ *req);
REBOOL SetClipboardStringData(REBREQ *req);

/***********************************************************************
**
*/ DEVICE_CMD Open_Clipboard(REBREQ *req)
/*
***********************************************************************/
{
SET_OPEN(req);
return DR_DONE;
}

/***********************************************************************
**
*/ DEVICE_CMD Close_Clipboard(REBREQ *req)
/*
***********************************************************************/
{
SET_CLOSED(req);
return DR_DONE;
}


/***********************************************************************
**
*/ DEVICE_CMD Read_Clipboard(REBREQ *req)
/*
***********************************************************************/
{
req->actual = 0;

if(!GetClipboardStringData(req)){
req->error = 20;
// just a random number... would be better to have some system for it
return DR_ERROR;
}

return DR_DONE;
}


/***********************************************************************
**
*/ DEVICE_CMD Write_Clipboard(REBREQ *req)
/*
** Expects data in UTF8 encoding in req->data!
**
***********************************************************************/
{
if(!SetClipboardStringData(req)) {
req->error = 20;
// just a random number... would be better to have some system for it
return DR_ERROR;
}
return DR_DONE;
}


/***********************************************************************
**
*/ DEVICE_CMD Poll_Clipboard(REBREQ *req)
/*
***********************************************************************/
{
return DR_DONE;
}


/***********************************************************************
**
** Command Dispatch Table (RDC_ enum order)
**
***********************************************************************/

static DEVICE_CMD_FUNC Dev_Cmds[RDC_MAX] =
{
0,
0,
Open_Clipboard,
Close_Clipboard,
Read_Clipboard,
Write_Clipboard,
Poll_Clipboard,
};

DEFINE_DEV(Dev_Clipboard, "Clipboard", 1, Dev_Cmds, RDC_MAX, 0);
79 changes: 79 additions & 0 deletions src/os/osx/sys-clipboard.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/***********************************************************************
**
** REBOL [R3] Language Interpreter and Run-time Environment
**
** Copyright 2021 Oldes
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
**
************************************************************************
**
** Title: Device: Clipboard access for macOS
** Author: Oldes
** Purpose:
** Provides a very simple interface to the clipboard for text.
** May be expanded in the future for images, etc.
**
************************************************************************/

#include <AppKit/AppKit.h>
#include "reb-host.h"
#include "host-lib.h" // for OS_Make

void EmptyClipboard(void){
[[NSPasteboard generalPasteboard] clearContents];
}

REBOOL GetClipboardStringData(REBREQ *req){
unsigned long len;
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSArray *classes=[NSArray arrayWithObject:[NSString class]];
NSDictionary *options=[NSDictionary dictionary];
NSArray *clipboardContent=[pasteboard readObjectsForClasses:classes options:options];

if(clipboardContent)
{
if(0<[clipboardContent count])
{
NSString *str=[clipboardContent objectAtIndex:0];
if(NULL!=str)
{
len = strlen([str UTF8String]);
// req->length is used when reading just part of the result
if (req->length > 0 && req->length < len)
len = req->length;

req->data = (REBYTE*)OS_Make(len+1);
req->actual = len;
COPY_STR(req->data, [str UTF8String], len);
return TRUE;
}
}
}
return FALSE;
}

REBOOL SetClipboardStringData(REBREQ *req){
const char *str = cs_cast(req->data);
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
[pasteboard clearContents];

NSString *nsstr = [NSString stringWithUTF8String:str];

if (!nsstr) return FALSE;
NSArray *arr = [NSArray arrayWithObject:[NSString stringWithUTF8String:str]];
BOOL res = [pasteboard writeObjects:arr];
req->actual = req->length;

return res;
}

0 comments on commit b35117a

Please sign in to comment.