Changeset fb623e2 in mainline for uspace/lib/libc/generic/clipboard.c


Ignore:
Timestamp:
2009-12-09T17:10:38Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1e4cada
Parents:
81235588
Message:

move from file-backed clipboard to service-backed clipboard
there is a possibility to do some type checking/conversion of the data stored in the clipboard (not used so far)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libc/generic/clipboard.c

    r81235588 rfb623e2  
    3333 * @brief System clipboard API.
    3434 *
    35  * The clipboard data is stored in a file and it is shared by the entire
    36  * system.
     35 * The clipboard data is managed by the clipboard service and it is shared by
     36 * the entire system.
    3737 *
    38  * @note Synchronization is missing. File locks would be ideal for the job.
    3938 */
    4039
    41 #include <stdlib.h>
     40#include <clipboard.h>
     41#include <ipc/services.h>
     42#include <ipc/clipboard.h>
     43#include <async.h>
    4244#include <string.h>
    43 #include <sys/types.h>
    44 #include <sys/stat.h>
    45 #include <fcntl.h>
    46 #include <macros.h>
    4745#include <errno.h>
    48 #include <clipboard.h>
     46#include <malloc.h>
    4947
    50 /** File used to store clipboard data */
    51 #define CLIPBOARD_FILE "/data/clip"
     48static int clip_phone = -1;
    5249
    53 #define CHUNK_SIZE      4096
     50/** Connect to clipboard server
     51 *
     52 */
     53static void clip_connect(void)
     54{
     55        while (clip_phone < 0)
     56                clip_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_CLIPBOARD, 0, 0);
     57}
    5458
    5559/** Copy string to clipboard.
    5660 *
    5761 * Sets the clipboard contents to @a str. Passing an empty string or NULL
    58  * makes the clipboard empty. 
     62 * makes the clipboard empty.
    5963 *
    60  * @param str   String to put to clipboard or NULL.
    61  * @return      Zero on success or negative error code.
     64 * @param str String to put to clipboard or NULL.
     65 *
     66 * @return Zero on success or negative error code.
     67 *
    6268 */
    6369int clipboard_put_str(const char *str)
    6470{
    65         int fd;
    66         const char *sp;
    67         ssize_t to_write, written, left;
    68 
    69         fd = open(CLIPBOARD_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0666);
    70         if (fd < 0)
    71                 return EIO;
    72 
    73         left = str_size(str);
    74         sp = str;
    75 
    76         while (left > 0) {
    77                 to_write = min(left, CHUNK_SIZE);
    78                 written = write(fd, sp, to_write);
    79 
    80                 if (written < 0) {
    81                         close(fd);
    82                         unlink(CLIPBOARD_FILE);
    83                         return EIO;
     71        size_t size = str_size(str);
     72       
     73        if (size == 0) {
     74                async_serialize_start();
     75                clip_connect();
     76               
     77                ipcarg_t rc = async_req_1_0(clip_phone, CLIPBOARD_PUT_DATA, CLIPBOARD_TAG_NONE);
     78               
     79                async_serialize_end();
     80               
     81                return (int) rc;
     82        } else {
     83                async_serialize_start();
     84                clip_connect();
     85               
     86                aid_t req = async_send_1(clip_phone, CLIPBOARD_PUT_DATA, CLIPBOARD_TAG_BLOB, NULL);
     87                ipcarg_t rc = async_data_write_start(clip_phone, (void *) str, size);
     88                if (rc != EOK) {
     89                        ipcarg_t rc_orig;
     90                        async_wait_for(req, &rc_orig);
     91                        async_serialize_end();
     92                        if (rc_orig == EOK)
     93                                return (int) rc;
     94                        else
     95                                return (int) rc_orig;
    8496                }
    85 
    86                 sp += written;
    87                 left -= written;
     97               
     98                async_wait_for(req, &rc);
     99                async_serialize_end();
     100               
     101                return (int) rc;
    88102        }
    89 
    90         if (close(fd) != EOK) {
    91                 unlink(CLIPBOARD_FILE);
    92                 return EIO;
    93         }
    94 
    95         return EOK;
    96103}
    97104
     
    100107 * Returns a new string that can be deallocated with free().
    101108 *
    102  * @param str   Here pointer to the newly allocated string is stored.
    103  * @return      Zero on success or negative error code.
     109 * @param str Here pointer to the newly allocated string is stored.
     110 *
     111 * @return Zero on success or negative error code.
     112 *
    104113 */
    105114int clipboard_get_str(char **str)
    106115{
    107         int fd;
    108         char *sbuf, *sp;
    109         ssize_t to_read, n_read, left;
    110         struct stat cbs;
    111 
    112         if (stat(CLIPBOARD_FILE, &cbs) != EOK)
    113                 return EIO;
    114 
    115         sbuf = malloc(cbs.size + 1);
    116         if (sbuf == NULL)
    117                 return ENOMEM;
    118 
    119         fd = open(CLIPBOARD_FILE, O_RDONLY);
    120         if (fd < 0) {
    121                 free(sbuf);
    122                 return EIO;
     116        /* Loop until clipboard read succesful */
     117        while (true) {
     118                async_serialize_start();
     119                clip_connect();
     120               
     121                ipcarg_t size;
     122                ipcarg_t tag;
     123                ipcarg_t rc = async_req_0_2(clip_phone, CLIPBOARD_CONTENT, &size, &tag);
     124               
     125                async_serialize_end();
     126               
     127                if (rc != EOK)
     128                        return (int) rc;
     129               
     130                char *sbuf;
     131               
     132                switch (tag) {
     133                case CLIPBOARD_TAG_NONE:
     134                        sbuf = malloc(1);
     135                        if (sbuf == NULL)
     136                                return ENOMEM;
     137                       
     138                        sbuf[0] = 0;
     139                        *str = sbuf;
     140                        return EOK;
     141                case CLIPBOARD_TAG_BLOB:
     142                        sbuf = malloc(size + 1);
     143                        if (sbuf == NULL)
     144                                return ENOMEM;
     145                       
     146                        async_serialize_start();
     147                       
     148                        aid_t req = async_send_1(clip_phone, CLIPBOARD_GET_DATA, tag, NULL);
     149                        rc = async_data_read_start(clip_phone, (void *) sbuf, size);
     150                        if (rc == EOVERFLOW) {
     151                                /*
     152                                 * The data in the clipboard has changed since
     153                                 * the last call of CLIPBOARD_CONTENT
     154                                 */
     155                                async_serialize_end();
     156                                break;
     157                        }
     158                       
     159                        if (rc != EOK) {
     160                                ipcarg_t rc_orig;
     161                                async_wait_for(req, &rc_orig);
     162                                async_serialize_end();
     163                                if (rc_orig == EOK)
     164                                        return (int) rc;
     165                                else
     166                                        return (int) rc_orig;
     167                        }
     168                       
     169                        async_wait_for(req, &rc);
     170                        async_serialize_end();
     171                       
     172                        if (rc == EOK) {
     173                                sbuf[size] = 0;
     174                                *str = sbuf;
     175                        }
     176                       
     177                        return rc;
     178                default:
     179                        return EINVAL;
     180                }
    123181        }
    124 
    125         sp = sbuf;
    126         left = cbs.size;
    127 
    128         while (left > 0) {
    129                 to_read = min(left, CHUNK_SIZE);
    130                 n_read = read(fd, sp, to_read);
    131 
    132                 if (n_read < 0) {
    133                         close(fd);
    134                         free(sbuf);
    135                         return EIO;
    136                 }
    137 
    138                 sp += n_read;
    139                 left -= n_read;
    140         }
    141 
    142         close(fd);
    143 
    144         *sp = '\0';
    145         *str = sbuf;
    146 
    147         return EOK;
    148182}
    149183
Note: See TracChangeset for help on using the changeset viewer.