Mac-Pasteboard

 view release on metacpan or  search on metacpan

Pasteboard.xs  view on Meta::CPAN

#define CFD_TO_SV_CHECKED(sv,cf) \
    CFD_TO_SV( sv, cf ); \
    CHECK_SV( sv );

#define CHECK_SV(sv) { \
	if ( sv == NULL ) { \
	    status = cNoMemErr; \
	    goto cleanup; \
	} \
    }

MODULE = Mac::Pasteboard		PACKAGE = Mac::Pasteboard

INCLUDE: constant-xs.inc

PROTOTYPES: DISABLE

#define SV_TO_C(c,sv,dflt) \
if ( SvOK( sv ) ) { \
    c = my_SvPVbyte_nolen( sv ); \
} else { \
    c = dflt; \
}

#define SV_TO_CF(cf,sv,dflt) \
    if ( SvOK( sv ) ) { \
	char *utf8_sv; \
	STRLEN utf8_sv_len; \
	utf8_sv = my_SvPVutf8( sv, utf8_sv_len ); \
	cf = CFStringCreateWithBytes( \
	    NULL, ( const unsigned char * ) utf8_sv, utf8_sv_len, \
	    PERL_ENCODING, 0 ); \
    } else { \
	cf = dflt; \
    }

char *
xs_pbl_variant()
    CODE:
#ifdef USE_PBL_BACKEND
	RETVAL = "PBL backend";
#else	/* def USE_PBL_BACKEND */
	RETVAL = "Pure XS";
#endif	/* def USE_PBL_BACKEND */
    OUTPUT:
	RETVAL

int
xs_pbl_is_at_least_monterey()
    CODE:
#ifdef MACOS_MONTEREY
	RETVAL = 1;
#else
	RETVAL = 0;
#endif
    OUTPUT:
	RETVAL

void
xs_pbl_create (SV * input_name)
    PPCODE:
#ifdef USE_PBL_BACKEND
	char *cname;
	char *created_name;
	void *pbref;
	long status;
	if (SvOK (input_name)) {
	    cname = my_SvPVbyte_nolen (input_name);
	} else {
	    cname = NULL;
	}
	status = (long) pbl_create (cname, &pbref, &created_name);
	EXTEND (SP, 3);
	PUSHs (sv_2mortal (newSViv (status)));
	PUSHs (sv_2mortal (newSVuv (PTR2UV (pbref))));
	if (created_name == NULL) {
	    PUSHs (sv_2mortal (newSV(0)));
	} else {
	    PUSHs (sv_2mortal (newSVpv (created_name, 0)));
	    FREE ("xs_pbl_create created_name", created_name);
	}
#else	/* def USE_PBL_BACKEND */
	void *pbref;
	long status;
	CFStringRef cf_name = NULL;
	CFStringRef cf_created = NULL;
	CFRange cf_range;
	SV *sv_stat;
	SV_TO_CF( cf_name, input_name, kPasteboardUniqueName );
	status = PasteboardCreate( cf_name, ( PasteboardRef * ) &pbref );
	sv_stat = sv_2mortal( newSViv( status ) );
	if ( status ) {	/* true indicates error */
	    EXTEND( SP, 1 );
	    PUSHs( sv_stat );
	} else {
#ifdef TIGER
	    SV *sv_created;
	    EXTEND( SP, 3 );
#else
	    EXTEND( SP, 2 );
#endif
	    PUSHs( sv_stat );
	    PUSHs( sv_2mortal( newSVuv( PTR2UV( pbref ) ) ) );
#ifdef TIGER
	    PasteboardCopyName( ( PasteboardRef ) pbref, &cf_created );
	    CF_TO_SV_CHECKED( sv_created, cf_created );
	    PUSHs( sv_2mortal( sv_created ) );
#endif
	}

	cleanup:

	if ( cf_name != NULL )
	    CFRelease( cf_name );
	if ( cf_created != NULL )
	    CFRelease( cf_created );
#endif	/* def USE_PBL_BACKEND */

long
xs_pbl_clear (void * pbref)
    CODE:
#ifdef USE_PBL_BACKEND
	RETVAL = (long) pbl_clear (pbref);
#else	/* def USE_PBL_BACKEND */
	RETVAL = ( long ) PasteboardClear( pbref );
#endif	/* def USE_PBL_BACKEND */
    OUTPUT:
	RETVAL

long
xs_pbl_copy (void * pbref, SV * data, unsigned long id, SV *sv_flavor, unsigned int flags)
    CODE:
#ifdef USE_PBL_BACKEND
	unsigned char * bytes;
	STRLEN size;
	char *cflavor;

	SV_TO_C( cflavor, sv_flavor, DEFAULT_FLAVOR );

	bytes = (unsigned char *) my_SvPVbyte (data, size);
	RETVAL = (long) pbl_copy (pbref, bytes, (size_t) size,
	    id, cflavor, flags);
#else	/* def USE_PBL_BACKEND */
	CFDataRef pbdata = NULL;
	CFStringRef cf_flavor = NULL;
	PasteboardSyncFlags sync;
	unsigned char * bytes;
	STRLEN size;
	OSStatus status;
	bytes = ( unsigned char * ) my_SvPVbyte( data, size );
	sync = PasteboardSynchronize( pbref );
	/* TODO clear if don't own pasteboard */
	if ( bytes == NULL ) {
	    pbdata = CFDataCreate( NULL, ( const unsigned char * ) "", 0 );
	} else {
	    pbdata = CFDataCreate( NULL, bytes, size );
	}

	SV_TO_CF( cf_flavor, sv_flavor, CFSTR( DEFAULT_FLAVOR ) );

	status = PasteboardPutItemFlavor( pbref, ( PasteboardItemID ) id,
		cf_flavor, pbdata, ( PasteboardFlavorFlags ) flags );
	if ( cf_flavor != NULL ) CFRelease( cf_flavor );
	if ( pbdata != NULL ) CFRelease( pbdata );
	RETVAL = ( long ) status;
#endif	/* def USE_PBL_BACKEND */
    OUTPUT:
	RETVAL

long
xs_pbl_paste( void *pbref, SV *id, SV *sv_flavor )
    PPCODE:
#ifdef USE_PBL_BACKEND
	unsigned char *data;
	size_t size;
	long status;
	unsigned long cid;
	int any;
	char *cflavor;
	PB_FLAVOR_FLAGS flags;
	if (SvOK (id)) {
	    any = 0;
	    cid = SvUV (id);
	} else {
	    any = 1;
	    cid = 0;
	}

	SV_TO_C( cflavor, sv_flavor, NULL );

	status = (long) pbl_paste (
	    pbref, any, cid, cflavor, &data, &size, &flags);
	EXTEND (SP, 3);
	PUSHs (sv_2mortal (newSViv (status)));
	if (data == NULL) {
	    PUSHs (sv_2mortal (newSV(0)));
	} else {
	    PUSHs (sv_2mortal (newSVpvn ((char *) data, (STRLEN) size)));
	    SvTAINTED_on( ST( 1 ) );
	    FREE ("xs_pbl_paste data", data);
	}
	PUSHs (sv_2mortal (newSVuv (flags)));
#else	/* def USE_PBL_BACKEND */
	int any;
	unsigned long cid;
	SV *sv_data = NULL;
	PB_FLAVOR_FLAGS flags;
	CFDataRef flavor_data = NULL;
	ItemCount item_inx;
	ItemCount pb_items;
	size_t size;	/* TODO STRLEN */
	OSStatus status;
	PasteboardSyncFlags sync;
	CFStringRef want_flavor = NULL;

	if (SvOK (id)) {
	    any = 0;
	    cid = SvUV (id);
	} else {
	    any = 1;
	    cid = 0;
	}

	SV_TO_CF( want_flavor, sv_flavor, kPasteboardClipboard );

	sync = PasteboardSynchronize( pbref );
	status = PasteboardGetItemCount( pbref, &pb_items );

	for (item_inx = pb_items; item_inx > 0; --item_inx) {
	    PasteboardItemID item_id;

	    status = PasteboardGetItemIdentifier( pbref, item_inx, &item_id );

Pasteboard.xs  view on Meta::CPAN

	}

	if (tags_s.os != NULL) {
	    (void)(hv_store (tags_h, "os", 2, newSVpv (tags_s.os, 0), 0));
	    FREE ("xs_pbl_uti_tags tags_s.os", tags_s.os);
	}
#endif
#else	/* def USE_PBL_BACKEND */
	CFStringRef cf_uti;
	CFStringRef cf_tag = NULL;
	OSStatus status;	/* Unused, but referred to by CF_TO_SV_CHECKED() */
	SV *sv_tag;
	SV_TO_CF( cf_uti, sv_uti, NULL );

	cf_tag = UTTypeCopyPreferredTagWithClass( cf_uti,
		kUTTagClassFilenameExtension );
	if ( cf_tag != NULL ) {
	    CF_TO_SV_CHECKED( sv_tag, cf_tag );
	    ( void ) hv_stores( tags_h, "extension", sv_tag );
	    CFRelease( cf_tag );
	    cf_tag = NULL;
	}

	cf_tag = UTTypeCopyPreferredTagWithClass( cf_uti,
		kUTTagClassMIMEType );
	if ( cf_tag != NULL ) {
	    CF_TO_SV_CHECKED( sv_tag, cf_tag );
	    ( void ) hv_stores( tags_h, "mime", sv_tag );
	    CFRelease( cf_tag );
	    cf_tag = NULL;
	}
#if ! defined(MACOS_MONTEREY)
	cf_tag = UTTypeCopyPreferredTagWithClass( cf_uti,
		kUTTagClassNSPboardType );
	if (cf_tag != NULL) {
	    CF_TO_SV_CHECKED( sv_tag, cf_tag );
	    ( void ) hv_stores( tags_h, "pboard", sv_tag );
	    CFRelease( cf_tag );
	    cf_tag = NULL;
	}

	cf_tag = UTTypeCopyPreferredTagWithClass( cf_uti,
		kUTTagClassOSType );
	if (cf_tag != NULL) {
	    CF_TO_SV_CHECKED( sv_tag, cf_tag );
	    ( void ) hv_stores( tags_h, "os", sv_tag );
	    CFRelease( cf_tag );
	    cf_tag = NULL;
	}
#endif
	cleanup:
	if ( cf_tag != NULL )
	    CFRelease( cf_tag );
#endif	/* def USE_PBL_BACKEND */
	RETVAL = tags_h;
    OUTPUT:
	RETVAL

void
xs_pbl_all( void *pbref, SV *sv_id, int want_data, SV *sv_conforms_to )
    PPCODE:
#ifdef USE_PBL_BACKEND
	pbl_rqst_t rqst;
	pbl_resp_t *resp;
	size_t num_resp;
	long status;
	size_t inx;
	if (SvOK (sv_id)) {
	    rqst.all = 0;
	    rqst.id = SvUV (sv_id);
	} else {
	    rqst.all = 1;
	    rqst.id = 0;
	}
	rqst.want_data = want_data;
	if (SvOK (sv_conforms_to)) {
	    rqst.conforms_to = my_SvPVbyte_nolen (sv_conforms_to);
	} else {
	    rqst.conforms_to = NULL;
	}
	status = pbl_all (pbref, &rqst, &resp, &num_resp);
	if (resp == NULL)
	    num_resp = 0;
	EXTEND (SP, 1 + num_resp);
	PUSHs (sv_2mortal (newSViv (status)));
	for (inx = 0; inx < num_resp; inx++) {
	    HV *flvr;
	    flvr = (HV *) sv_2mortal ((SV *)newHV());
	    /* Cast to void to supress 'expression result unused' */
	    (void)(
		hv_store (flvr, "flags", 5, newSVuv (resp[inx].flags), 0));
	    (void)(hv_store (flvr, "id", 2, newSVuv (resp[inx].id), 0));
	    if (resp[inx].flavor != NULL)
		(void)(hv_store (flvr, "flavor", 6,
		    newSVpv (resp[inx].flavor, 0), 0));
	    if ( resp[inx].data != NULL ) {
		SV * data = newSVpvn( ( char * ) resp[inx].data,
		    resp[inx].size );
		SvTAINTED_on( data );
		( void ) ( hv_store( flvr, "data", 4, data , 0) );
	    }
	    PUSHs (newRV_inc ((SV *) flvr));
	}
	pbl_free_all (resp, num_resp);
#else	/* def USE_PBL_BACKEND */
	int all;
	CFStringRef cf_conforms_to;
	CFArrayRef flavor_array = NULL;
	CFDataRef	flavor_data = NULL;
	unsigned long id;
	ItemCount item_inx;
	ItemCount pb_items;
	OSStatus status;
	PasteboardSyncFlags sync;

	if ( SvOK( sv_id ) ) {
	    all = 0;
	    id = SvUV( sv_id );
	} else {
	    all = 1;
	    id = 0;



( run in 1.992 second using v1.01-cache-2.11-cpan-71847e10f99 )