root/src/haiku_select.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_clipboard_object
  2. be_find_clipboard_data_1
  3. be_set_clipboard_data_1
  4. be_update_clipboard_count
  5. be_find_clipboard_data
  6. be_set_clipboard_data
  7. clipboard_owner_p
  8. primary_owner_p
  9. secondary_owner_p
  10. be_clipboard_owner_p
  11. be_clipboard_init
  12. be_enum_message
  13. be_get_refs_data
  14. be_get_point_data
  15. be_get_message_data
  16. be_get_message_type
  17. be_set_message_type
  18. be_get_message_message
  19. be_create_simple_message
  20. be_add_message_data
  21. be_add_refs_data
  22. be_add_point_data
  23. be_add_message_message
  24. be_lock_clipboard_message
  25. be_unlock_clipboard
  26. be_handle_clipboard_changed_message
  27. be_start_watching_selection
  28. be_selection_outdated_p
  29. be_get_clipboard_count

     1 /* Haiku window system selection support. Hey Emacs, this is -*- C++ -*-
     2    Copyright (C) 2021-2023 Free Software Foundation, Inc.
     3 
     4 This file is part of GNU Emacs.
     5 
     6 GNU Emacs is free software: you can redistribute it and/or modify
     7 it under the terms of the GNU General Public License as published by
     8 the Free Software Foundation, either version 3 of the License, or (at
     9 your option) any later version.
    10 
    11 GNU Emacs is distributed in the hope that it will be useful,
    12 but WITHOUT ANY WARRANTY; without even the implied warranty of
    13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14 GNU General Public License for more details.
    15 
    16 You should have received a copy of the GNU General Public License
    17 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    18 
    19 #include <config.h>
    20 
    21 #include <Application.h>
    22 #include <Clipboard.h>
    23 #include <Message.h>
    24 #include <Path.h>
    25 #include <Entry.h>
    26 
    27 #include <cstdlib>
    28 #include <cstring>
    29 
    30 #include "haikuselect.h"
    31 
    32 /* The clipboard object representing the primary selection.  */
    33 static BClipboard *primary = NULL;
    34 
    35 /* The clipboard object representing the secondary selection.  */
    36 static BClipboard *secondary = NULL;
    37 
    38 /* The clipboard object used by other programs, representing the
    39    clipboard.  */
    40 static BClipboard *system_clipboard = NULL;
    41 
    42 /* The number of times the system clipboard has changed.  */
    43 static int64 count_clipboard = -1;
    44 
    45 /* The number of times the primary selection has changed.  */
    46 static int64 count_primary = -1;
    47 
    48 /* The number of times the secondary selection has changed.  */
    49 static int64 count_secondary = -1;
    50 
    51 /* Whether or not we currently think Emacs owns the primary
    52    selection.  */
    53 static bool owned_primary;
    54 
    55 /* Likewise for the secondary selection.  */
    56 static bool owned_secondary;
    57 
    58 /* And the clipboard.  */
    59 static bool owned_clipboard;
    60 
    61 static BClipboard *
    62 get_clipboard_object (enum haiku_clipboard clipboard)
    63 {
    64   switch (clipboard)
    65     {
    66     case CLIPBOARD_PRIMARY:
    67       return primary;
    68 
    69     case CLIPBOARD_SECONDARY:
    70       return secondary;
    71 
    72     case CLIPBOARD_CLIPBOARD:
    73       return system_clipboard;
    74     }
    75 
    76   abort ();
    77 }
    78 
    79 static char *
    80 be_find_clipboard_data_1 (BClipboard *cb, const char *type, ssize_t *len)
    81 {
    82   BMessage *data;
    83   const char *ptr;
    84   ssize_t nbytes;
    85   void *value;
    86 
    87   if (!cb->Lock ())
    88     return NULL;
    89 
    90   data = cb->Data ();
    91 
    92   if (!data)
    93     {
    94       cb->Unlock ();
    95       return NULL;
    96     }
    97 
    98   data->FindData (type, B_MIME_TYPE, (const void **) &ptr,
    99                   &nbytes);
   100 
   101   if (!ptr)
   102     {
   103       cb->Unlock ();
   104       return NULL;
   105     }
   106 
   107   if (len)
   108     *len = nbytes;
   109 
   110   value = malloc (nbytes);
   111 
   112   if (!data)
   113     {
   114       cb->Unlock ();
   115       return NULL;
   116     }
   117 
   118   memcpy (value, ptr, nbytes);
   119   cb->Unlock ();
   120 
   121   return (char *) value;
   122 }
   123 
   124 static void
   125 be_set_clipboard_data_1 (BClipboard *cb, const char *type, const char *data,
   126                          ssize_t len, bool clear)
   127 {
   128   BMessage *message_data;
   129 
   130   if (!cb->Lock ())
   131     return;
   132 
   133   if (clear)
   134     cb->Clear ();
   135 
   136   message_data = cb->Data ();
   137 
   138   if (!message_data)
   139     {
   140       cb->Unlock ();
   141       return;
   142     }
   143 
   144   if (data)
   145     {
   146       if (message_data->ReplaceData (type, B_MIME_TYPE, data, len)
   147           == B_NAME_NOT_FOUND)
   148         message_data->AddData (type, B_MIME_TYPE, data, len);
   149     }
   150   else
   151     message_data->RemoveName (type);
   152 
   153   cb->Commit ();
   154   cb->Unlock ();
   155 }
   156 
   157 void
   158 be_update_clipboard_count (enum haiku_clipboard id)
   159 {
   160   switch (id)
   161     {
   162     case CLIPBOARD_CLIPBOARD:
   163       count_clipboard = system_clipboard->SystemCount ();
   164       owned_clipboard = true;
   165       break;
   166 
   167     case CLIPBOARD_PRIMARY:
   168       count_primary = primary->SystemCount ();
   169       owned_primary = true;
   170       break;
   171 
   172     case CLIPBOARD_SECONDARY:
   173       count_secondary = secondary->SystemCount ();
   174       owned_secondary = true;
   175       break;
   176     }
   177 }
   178 
   179 char *
   180 be_find_clipboard_data (enum haiku_clipboard id, const char *type,
   181                         ssize_t *len)
   182 {
   183   return be_find_clipboard_data_1 (get_clipboard_object (id),
   184                                    type, len);
   185 }
   186 
   187 void
   188 be_set_clipboard_data (enum haiku_clipboard id, const char *type,
   189                        const char *data, ssize_t len, bool clear)
   190 {
   191   be_update_clipboard_count (id);
   192 
   193   be_set_clipboard_data_1 (get_clipboard_object (id), type,
   194                            data, len, clear);
   195 }
   196 
   197 static bool
   198 clipboard_owner_p (void)
   199 {
   200   return (count_clipboard >= 0
   201           && (count_clipboard + 1
   202               == system_clipboard->SystemCount ()));
   203 }
   204 
   205 static bool
   206 primary_owner_p (void)
   207 {
   208   return (count_primary >= 0
   209           && (count_primary + 1
   210               == primary->SystemCount ()));
   211 }
   212 
   213 static bool
   214 secondary_owner_p (void)
   215 {
   216   return (count_secondary >= 0
   217           && (count_secondary + 1
   218               == secondary->SystemCount ()));
   219 }
   220 
   221 bool
   222 be_clipboard_owner_p (enum haiku_clipboard clipboard)
   223 {
   224   switch (clipboard)
   225     {
   226     case CLIPBOARD_PRIMARY:
   227       return primary_owner_p ();
   228 
   229     case CLIPBOARD_SECONDARY:
   230       return secondary_owner_p ();
   231 
   232     case CLIPBOARD_CLIPBOARD:
   233       return clipboard_owner_p ();
   234     }
   235 
   236   abort ();
   237 }
   238 
   239 void
   240 be_clipboard_init (void)
   241 {
   242   system_clipboard = new BClipboard ("system");
   243   primary = new BClipboard ("primary");
   244   secondary = new BClipboard ("secondary");
   245 }
   246 
   247 int
   248 be_enum_message (void *message, int32 *tc, int32 index,
   249                  int32 *count, const char **name_return)
   250 {
   251   BMessage *msg = (BMessage *) message;
   252   type_code type;
   253   char *name;
   254   status_t rc;
   255 
   256   rc = msg->GetInfo (B_ANY_TYPE, index, &name, &type, count);
   257 
   258   if (rc != B_OK)
   259     return 1;
   260 
   261   *tc = type;
   262   *name_return = name;
   263   return 0;
   264 }
   265 
   266 int
   267 be_get_refs_data (void *message, const char *name,
   268                   int32 index, char **path_buffer)
   269 {
   270   status_t rc;
   271   BEntry entry;
   272   BPath path;
   273   entry_ref ref;
   274   BMessage *msg;
   275 
   276   msg = (BMessage *) message;
   277   rc = msg->FindRef (name, index, &ref);
   278 
   279   if (rc != B_OK)
   280     return 1;
   281 
   282   rc = entry.SetTo (&ref, 0);
   283 
   284   if (rc != B_OK)
   285     return 1;
   286 
   287   rc = entry.GetPath (&path);
   288 
   289   if (rc != B_OK)
   290     return 1;
   291 
   292   *path_buffer = strdup (path.Path ());
   293   return 0;
   294 }
   295 
   296 int
   297 be_get_point_data (void *message, const char *name,
   298                    int32 index, float *x, float *y)
   299 {
   300   status_t rc;
   301   BMessage *msg;
   302   BPoint point;
   303 
   304   msg = (BMessage *) message;
   305   rc = msg->FindPoint (name, index, &point);
   306 
   307   if (rc != B_OK)
   308     return 1;
   309 
   310   *x = point.x;
   311   *y = point.y;
   312 
   313   return 0;
   314 }
   315 
   316 int
   317 be_get_message_data (void *message, const char *name,
   318                      int32 type_code, int32 index,
   319                      const void **buf_return,
   320                      ssize_t *size_return)
   321 {
   322   BMessage *msg = (BMessage *) message;
   323 
   324   return msg->FindData (name, type_code,
   325                         index, buf_return, size_return) != B_OK;
   326 }
   327 
   328 uint32
   329 be_get_message_type (void *message)
   330 {
   331   BMessage *msg = (BMessage *) message;
   332 
   333   return msg->what;
   334 }
   335 
   336 void
   337 be_set_message_type (void *message, uint32 what)
   338 {
   339   BMessage *msg = (BMessage *) message;
   340 
   341   msg->what = what;
   342 }
   343 
   344 void *
   345 be_get_message_message (void *message, const char *name,
   346                         int32 index)
   347 {
   348   BMessage *msg = (BMessage *) message;
   349   BMessage *out = new (std::nothrow) BMessage;
   350 
   351   if (!out)
   352     return NULL;
   353 
   354   if (msg->FindMessage (name, index, out) != B_OK)
   355     {
   356       delete out;
   357       return NULL;
   358     }
   359 
   360   return out;
   361 }
   362 
   363 void *
   364 be_create_simple_message (void)
   365 {
   366   return new BMessage (B_SIMPLE_DATA);
   367 }
   368 
   369 int
   370 be_add_message_data (void *message, const char *name,
   371                      int32 type_code, const void *buf,
   372                      ssize_t buf_size)
   373 {
   374   BMessage *msg = (BMessage *) message;
   375 
   376   return msg->AddData (name, type_code, buf, buf_size) != B_OK;
   377 }
   378 
   379 int
   380 be_add_refs_data (void *message, const char *name,
   381                   const char *filename)
   382 {
   383   BEntry entry (filename);
   384   entry_ref ref;
   385   BMessage *msg = (BMessage *) message;
   386 
   387   if (entry.InitCheck () != B_OK)
   388     return 1;
   389 
   390   if (entry.GetRef (&ref) != B_OK)
   391     return 1;
   392 
   393   return msg->AddRef (name, &ref) != B_OK;
   394 }
   395 
   396 int
   397 be_add_point_data (void *message, const char *name,
   398                    float x, float y)
   399 {
   400   BMessage *msg = (BMessage *) message;
   401 
   402   return msg->AddPoint (name, BPoint (x, y)) != B_OK;
   403 }
   404 
   405 int
   406 be_add_message_message (void *message, const char *name,
   407                         void *data)
   408 {
   409   BMessage *msg = (BMessage *) message;
   410   BMessage *data_message = (BMessage *) data;
   411 
   412   if (msg->AddMessage (name, data_message) != B_OK)
   413     return 1;
   414 
   415   return 0;
   416 }
   417 
   418 int
   419 be_lock_clipboard_message (enum haiku_clipboard clipboard,
   420                            void **message_return, bool clear)
   421 {
   422   BClipboard *board;
   423 
   424   board = get_clipboard_object (clipboard);
   425 
   426   if (!board->Lock ())
   427     return 1;
   428 
   429   if (clear)
   430     board->Clear ();
   431 
   432   *message_return = board->Data ();
   433   return 0;
   434 }
   435 
   436 void
   437 be_unlock_clipboard (enum haiku_clipboard clipboard, bool discard)
   438 {
   439   BClipboard *board;
   440 
   441   board = get_clipboard_object (clipboard);
   442 
   443   if (discard)
   444     board->Revert ();
   445   else
   446     board->Commit ();
   447 
   448   board->Unlock ();
   449 }
   450 
   451 void
   452 be_handle_clipboard_changed_message (void)
   453 {
   454   int64 n_clipboard, n_primary, n_secondary;
   455 
   456   n_clipboard = system_clipboard->SystemCount ();
   457   n_primary = primary->SystemCount ();
   458   n_secondary = secondary->SystemCount ();
   459 
   460   if (count_clipboard != -1
   461       && (n_clipboard > count_clipboard + 1)
   462       && owned_clipboard)
   463     {
   464       owned_clipboard = false;
   465       haiku_selection_disowned (CLIPBOARD_CLIPBOARD,
   466                                 n_clipboard);
   467     }
   468 
   469   if (count_primary != -1
   470       && (n_primary > count_primary + 1)
   471       && owned_primary)
   472     {
   473       owned_primary = false;
   474       haiku_selection_disowned (CLIPBOARD_PRIMARY,
   475                                 n_primary);
   476     }
   477 
   478   if (count_secondary != -1
   479       && (n_secondary > count_secondary + 1)
   480       && owned_secondary)
   481     {
   482       owned_secondary = false;
   483       haiku_selection_disowned (CLIPBOARD_SECONDARY,
   484                                 n_secondary);
   485     }
   486 }
   487 
   488 void
   489 be_start_watching_selection (enum haiku_clipboard id)
   490 {
   491   BClipboard *clipboard;
   492 
   493   clipboard = get_clipboard_object (id);
   494   clipboard->StartWatching (be_app);
   495 }
   496 
   497 bool
   498 be_selection_outdated_p (enum haiku_clipboard id, int64 count)
   499 {
   500   if (id == CLIPBOARD_CLIPBOARD && count_clipboard > count)
   501     return true;
   502 
   503   if (id == CLIPBOARD_PRIMARY && count_primary > count)
   504     return true;
   505 
   506   if (id == CLIPBOARD_SECONDARY && count_secondary > count)
   507     return true;
   508 
   509   return false;
   510 }
   511 
   512 int64
   513 be_get_clipboard_count (enum haiku_clipboard id)
   514 {
   515   BClipboard *clipboard;
   516 
   517   clipboard = get_clipboard_object (id);
   518   return clipboard->SystemCount ();
   519 }

/* [<][>][^][v][top][bottom][index][help] */