⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clipboard.c

📁 在ADS环境下MiniGUI的源码
💻 C
字号:
/*
** $Id: clipboard.c,v 1.13 2004/06/26 07:49:32 weiym Exp $
**
** clipboard.c: The implementation of Clipboard.
**
** Copyright (C) 2003 Feynman Software.
**
** Create date: 2003/12/xx
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common.h"

#ifdef _CLIPBOARD_SUPPORT

#include "minigui.h"
#include "clipboard.h"

#ifndef _LITE_VERSION
#include <semaphore.h>
#elif !defined (_STAND_ALONE)
#include "client.h"
#endif


typedef struct _CLIPBOARD
{
    char name [LEN_CLIPBOARD_NAME + 1];
    unsigned char *buff;
    size_t buff_len;
    size_t data_len;
} CLIPBOARD;


#ifndef _LITE_VERSION
static sem_t cb_lock;
#endif

static CLIPBOARD cbs [NR_CLIPBOARDS];

static int create_clip_board (const char* cb_name, size_t size)
{
    int i;
    int empty = -1;

    if (size <= 0)
        return -1;

    for (i = 0; i < NR_CLIPBOARDS; i++) {
        if (strncmp (cb_name, cbs [i].name, LEN_CLIPBOARD_NAME) == 0) {
            fprintf (stderr, "create clip board error: already existed name.\n");
            return CBERR_BADNAME;
        }
        if (empty < 0 && cbs [i].name [0] == '\0') {
            empty = i;
        }
    }

    if (empty >= 0) {
        if ((cbs [empty].buff = malloc (size)) == NULL) {
            return CBERR_NOMEM;
        }
        strncpy (cbs [empty].name, cb_name, LEN_CLIPBOARD_NAME);
        cbs[empty].name[LEN_CLIPBOARD_NAME] = 0;
        cbs [empty].buff_len = size;
        cbs [empty].data_len = 0;
    }

    return CBERR_OK;
}

#ifdef _LITE_VERSION
#ifdef _STAND_ALONE
int GUIAPI CreateClipBoard (const char* cb_name, size_t size)
{
    return create_clip_board (cb_name, size);
}
#else

int GUIAPI CreateClipBoard (const char* cb_name, size_t size)
{
    if (mgIsServer) {
        return create_clip_board (cb_name, size);
    }
    else {
        REQ_CLIPBOARD req_data;
        REQUEST request = {REQID_CLIPBOARD, &req_data, sizeof (REQ_CLIPBOARD)};
        int ret;

        req_data.id = CBREQ_CREATE;

        strncpy (req_data.name, cb_name, LEN_CLIPBOARD_NAME);
        req_data.name[LEN_CLIPBOARD_NAME] = '\0';

        req_data.len_data = size;

        cli_request (&request, &ret, sizeof(ret));

        return ret;
    }
}
#endif

#else

int GUIAPI CreateClipBoard (const char* cb_name, size_t size)
{
    int ret;

    sem_wait (&cb_lock);
    ret = create_clip_board (cb_name, size);
    sem_post (&cb_lock);

    return ret;
}

#endif

int GUIAPI destroy_clip_board (const char* cb_name)
{
    int i;

    for (i = 0; i < NR_CLIPBOARDS; i++) {
        if (strcmp (cb_name, cbs [i].name) == 0) {
            free (cbs [i].buff);
            cbs [i].name [0] = '\0';
            cbs [i].buff = NULL;
            cbs [i].buff_len = 0;
            cbs [i].data_len = 0;

            return CBERR_OK;
        }
    }

    return CBERR_BADNAME;
}

#ifdef _LITE_VERSION
#ifdef _STAND_ALONE
int GUIAPI DestroyClipBoard (const char* cb_name)
{
    return destroy_clip_board (cb_name);
}
#else
int GUIAPI DestroyClipBoard (const char* cb_name)
{
    if (mgIsServer) {
        return destroy_clip_board (cb_name);
    }
    else {
        REQ_CLIPBOARD req_data;
        REQUEST request = {REQID_CLIPBOARD, &req_data, sizeof (REQ_CLIPBOARD)};
        int ret;

        req_data.id = CBREQ_DESTROY;

        strncpy (req_data.name, cb_name, LEN_CLIPBOARD_NAME);
        req_data.name[LEN_CLIPBOARD_NAME] = '\0';

        cli_request (&request, &ret, sizeof (ret));

        return ret;
    }
}
#endif

#else

int GUIAPI DestroyClipBoard (const char* cb_name)
{
    int ret;

    sem_wait (&cb_lock);
    ret = destroy_clip_board (cb_name);
    sem_post (&cb_lock);

    return ret;
}
#endif

static int set_clip_board_data (const char* cb_name, void* data, size_t n, int cbop)
{
    int i;
    CLIPBOARD* cb = NULL;
    int dataLen;

    for (i = 0; i < NR_CLIPBOARDS; i++) {
        if (strncmp (cb_name, cbs [i].name, LEN_CLIPBOARD_NAME) == 0) {
            cb = cbs + i;
            break;
        }
    }

    if (cb == NULL)
        return CBERR_BADNAME;

    if (cbop == CBOP_APPEND) {
        dataLen = MIN (n, cb->buff_len - cb->data_len);
        memcpy (cb->buff + cb->data_len, data, dataLen);
        cb->data_len += dataLen;
    }
    else {
        cb->data_len = MIN (n, cb->buff_len);
        if (data && cb->data_len > 0)
            memcpy (cb->buff, data, cb->data_len);
    }

    return CBERR_OK;
}

#ifdef _LITE_VERSION
#ifdef _STAND_ALONE
int GUIAPI SetClipBoardData (const char* cb_name, void* data, size_t n, int cbop)
{
    return set_clip_board_data (cb_name, data, n, cbop);
}
#else
int GUIAPI SetClipBoardData (const char* cb_name, void* data, size_t n, int cbop)
{
    if (mgIsServer) {
        return set_clip_board_data (cb_name, data, n, cbop);
    }
    else {
        REQ_CLIPBOARD* req_data;
        REQUEST request; 
        int ret;

        req_data = ALLOCATE_LOCAL (sizeof (REQ_CLIPBOARD) + n);
        if (req_data == NULL)
            return CBERR_NOMEM;

        req_data->id = CBREQ_SETDATA;
        strncpy (req_data->name, cb_name, LEN_CLIPBOARD_NAME);
        req_data->name[LEN_CLIPBOARD_NAME] = '\0';

        req_data->len_data = n;
        memcpy ((char*)(req_data+1), data, n);

        req_data->cbop = cbop;

        request.id = REQID_CLIPBOARD;
        request.data = req_data;
        request.len_data = sizeof (REQ_CLIPBOARD) + n;

        cli_request (&request, &ret, sizeof (ret));

        DEALLOCATE_LOCAL (req_data);
        return ret;
    }
}
#endif

#else

int GUIAPI SetClipBoardData (const char* cb_name, void* data, size_t n, int cbop)
{
    int ret;

    sem_wait (&cb_lock);
    ret = set_clip_board_data (cb_name, data, n, cbop);
    sem_post (&cb_lock);

    return ret;
}

#endif

static size_t get_clip_board_data_len (const char* cb_name)
{
    int i;
    CLIPBOARD* cb = NULL;

    for (i = 0; i < NR_CLIPBOARDS; i++) {
        if (strncmp (cb_name, cbs [i].name, LEN_CLIPBOARD_NAME) == 0) {
            cb = cbs + i;
            break;
        }
    }

    if (cb)
        return cb->data_len;
    return 0;
}

#ifdef _LITE_VERSION
#ifdef _STAND_ALONE
size_t GUIAPI GetClipBoardDataLen (const char* cb_name)
{
    return get_clip_board_data_len (cb_name);
}
#else
size_t GUIAPI GetClipBoardDataLen (const char* cb_name)
{
    if (mgIsServer) {
        return get_clip_board_data_len (cb_name);
    }
    else {
        REQ_CLIPBOARD req_data;
        REQUEST request = {REQID_CLIPBOARD, &req_data, sizeof (REQ_CLIPBOARD)};
        int reply[2];

        req_data.id = CBREQ_GETDATALEN;
        strncpy (req_data.name, cb_name, LEN_CLIPBOARD_NAME);
        req_data.name[LEN_CLIPBOARD_NAME] = '\0';
        req_data.len_data = 0;

        cli_request (&request, &reply, sizeof (reply));

        if (reply[0] == CBERR_OK)
            return reply[1];
        else
            return reply[0];
    }
}
#endif

#else

size_t GUIAPI GetClipBoardDataLen (const char* cb_name)
{
    int ret;

    sem_wait (&cb_lock);
    ret = get_clip_board_data_len (cb_name);
    sem_post (&cb_lock);

    return ret;
}

#endif

static CLIPBOARD* get_clipboard (const char *cb_name)
{
    int i;
    for (i = 0; i < NR_CLIPBOARDS; i++) {
        if (strncmp (cb_name, cbs [i].name, LEN_CLIPBOARD_NAME) == 0) {
            return (cbs + i);
        }
    }
    return NULL;
}

static size_t get_clip_board_data (const char* cb_name, void* data, size_t n)
{
    int i;
    CLIPBOARD* cb = NULL;
    int copied_len = 0;

    if (!data || n <= 0)
        return -1;

    for (i = 0; i < NR_CLIPBOARDS; i++) {
        if (strncmp (cb_name, cbs [i].name, LEN_CLIPBOARD_NAME) == 0) {
            cb = cbs + i;
            break;
        }
    }

    if (cb) {
        copied_len = MIN (n, cb->data_len);
        if (copied_len > 0) {
            memcpy (data, cb->buff, copied_len);
        }
    }

    return copied_len;
}

#ifdef _LITE_VERSION
#ifdef _STAND_ALONE
size_t GUIAPI GetClipBoardData (const char* cb_name, void* data, size_t n)
{
    return get_clip_board_data (cb_name, data, n);
}
#else
size_t GUIAPI GetClipBoardData (const char* cb_name, void* data, size_t n)
{
    if (mgIsServer) {
        return get_clip_board_data (cb_name, data, n);
    }
    else {
        REQ_CLIPBOARD req_data;
        REQUEST request = {REQID_CLIPBOARD, &req_data, sizeof (REQ_CLIPBOARD)};
        int* reply;

        reply = (int*)ALLOCATE_LOCAL (2*sizeof(int) + n);

        req_data.id = CBREQ_GETDATA;
        strncpy (req_data.name, cb_name, LEN_CLIPBOARD_NAME);
        req_data.name[LEN_CLIPBOARD_NAME] = '\0';
        //FIXME
        req_data.len_data = n;

        cli_request (&request, (void*)reply, 2*sizeof(int) + n);

        if (*reply == CBERR_OK) {
            memcpy (data, (void*)(reply+2), *(reply+1));
        }

        DEALLOCATE_LOCAL (reply);
        return *(reply+1);
    }
}
#endif

#else

size_t GUIAPI GetClipBoardData (const char* cb_name, void* data, size_t n)
{
    int ret;

    sem_wait (&cb_lock);
    ret = get_clip_board_data (cb_name, data, n);
    sem_post (&cb_lock);

    return ret;
}

#endif

static int get_clip_board_byte (const char* cb_name, int index, unsigned char* byte)
{
    int i;
    CLIPBOARD* cb = NULL;

    for (i = 0; i < NR_CLIPBOARDS; i++) {
        if (strncmp (cb_name, cbs [i].name, LEN_CLIPBOARD_NAME) == 0) {
            cb = cbs + i;
            break;
        }
    }

    if (cb) {
        if (index >= cb->data_len)
            return CBERR_NOMEM;
        *byte = cb->buff [index];
    }
    else
        return CBERR_BADNAME;

    return CBERR_OK;
}

#ifdef _LITE_VERSION
#ifdef _STAND_ALONE
int GUIAPI GetClipBoardByte (const char* cb_name, int index, unsigned char* byte)
{
    return get_clip_board_byte (cb_name, index, byte);
}
#else
int GUIAPI GetClipBoardByte (const char* cb_name, int index, unsigned char* byte)
{
    if (mgIsServer) {
        return get_clip_board_byte (cb_name, index, byte);
    }
    else {
        REQ_CLIPBOARD req_data;
        REQUEST request = {REQID_CLIPBOARD, &req_data, sizeof (REQ_CLIPBOARD)};
        int reply[2];

        req_data.id = CBREQ_GETBYTE;
        strncpy (req_data.name, cb_name, LEN_CLIPBOARD_NAME);
        req_data.name[LEN_CLIPBOARD_NAME] = '\0';
        req_data.len_data = index;

        cli_request (&request, &reply, sizeof (reply));

        if (reply[0] == CBERR_OK)
            *byte = (unsigned char) reply[1];

        return reply[0];
    }
}
#endif

#else

int GUIAPI GetClipBoardByte (const char* cb_name, int index, unsigned char* byte)
{
    int ret;

    sem_wait (&cb_lock);
    ret = get_clip_board_byte (cb_name, index, byte);
    sem_post (&cb_lock);

    return ret;
}

#endif

#if defined(_LITE_VERSION) && !defined(_STAND_ALONE)
int send_reply (int clifd, const void* reply, int len);

int clipboard_op (int cli, int clifd, void* buff, size_t len)
{
    REQ_CLIPBOARD* request = (REQ_CLIPBOARD*) buff;
    int ret;

    switch (request->id) {
        case CBREQ_CREATE:
            ret = create_clip_board (request->name, request->len_data);
            break;

        case CBREQ_DESTROY:
            ret = destroy_clip_board (request->name);
            break;

        case CBREQ_SETDATA:
            ret = set_clip_board_data (request->name, (char*)buff + sizeof(REQ_CLIPBOARD), 
                                       request->len_data, request->cbop);
            break;

        case CBREQ_GETDATALEN:
        {
            int attlen;
            attlen = get_clip_board_data_len (request->name);
            ret = CBERR_OK;
            send_reply (clifd, &ret, sizeof (ret));
            sock_write (clifd, &attlen, sizeof(int));
            return SOCKERR_OK;
        }

        case CBREQ_GETDATA:
        {
            CLIPBOARD *cb = get_clipboard (request->name);
            int dlen;
            if (!cb) {
                ret = -1;
                send_reply (clifd, &ret, sizeof (ret));
                return SOCKERR_OK;
            }
            ret = CBERR_OK;
            send_reply (clifd, &ret, sizeof (ret));

            dlen =  MIN(request->len_data, cb->data_len);
            sock_write (clifd, &dlen, sizeof (dlen));

            sock_write (clifd, cb->buff, dlen);
            return SOCKERR_OK;
        }

        case CBREQ_GETBYTE:
        {
            unsigned char ch;
            get_clip_board_byte (request->name, request->len_data, &ch);
            ret = CBERR_OK;
            send_reply (clifd, &ret, sizeof (ret));
            sock_write (clifd, &ch, sizeof(ch));
            return SOCKERR_OK;
        }
    }

    ret = CBERR_OK;
    send_reply (clifd, &ret, sizeof (ret));

    return SOCKERR_OK;
}

#endif


void InitClipBoard (void)
{
#ifndef _LITE_VERSION
    sem_init (&cb_lock, 0, 1);
#endif

#if defined(_LITE_VERSION) && !defined(_STAND_ALONE)
    if (mgIsServer)
#endif
        create_clip_board (CBNAME_TEXT, 1024);

}

void TerminateClipBoard (void)
{
#if defined(_LITE_VERSION) && !defined(_STAND_ALONE)
    if (mgIsServer)
#endif
    {
        int i;

        for (i = 0; i < NR_CLIPBOARDS; i++) {
            if (cbs [i].name [0])
                free (cbs [i].buff);
        }
    }

#ifndef _LITE_VERSION
    sem_destroy (&cb_lock);
#endif
}

#endif /* _CLIPBOARD_SUPPORT */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -