(interactive "e")
(let* ((string (caddr event))
(window (posn-window (event-start event))))
- (with-selected-window window
- (raise-frame)
- (dnd-handle-one-url window 'private (concat "file:" string)))))
+ (cond
+ ((assoc "refs" string)
+ (with-selected-window window
+ (raise-frame)
+ (dolist (filename (cddr (assoc "refs" string)))
+ (dnd-handle-one-url window 'private
+ (concat "file:" filename)))))
+ (t (message "Don't know how to drop: %s" event)))))
(define-key special-event-map [drag-n-drop]
'haiku-dnd-handle-drag-n-drop-event)
return sizeof (struct haiku_menu_bar_help_event);
case ZOOM_EVENT:
return sizeof (struct haiku_zoom_event);
- case REFS_EVENT:
- return sizeof (struct haiku_refs_event);
+ case DRAG_AND_DROP_EVENT:
+ return sizeof (struct haiku_drag_and_drop_event);
case APP_QUIT_REQUESTED_EVENT:
return sizeof (struct haiku_app_quit_requested_event);
case DUMMY_EVENT:
#include <config.h>
#include <Clipboard.h>
+#include <Message.h>
+#include <Path.h>
+#include <Entry.h>
#include <cstdlib>
#include <cstring>
primary = new BClipboard ("primary");
secondary = new BClipboard ("secondary");
}
+
+int
+be_enum_message (void *message, int32 *tc, int32 index,
+ int32 *count, const char **name_return)
+{
+ BMessage *msg = (BMessage *) message;
+ type_code type;
+ char *name;
+ status_t rc;
+
+ rc = msg->GetInfo (B_ANY_TYPE, index, &name, &type, count);
+
+ if (rc != B_OK)
+ return 1;
+
+ *tc = type;
+ *name_return = name;
+ return 0;
+}
+
+int
+be_get_refs_data (void *message, const char *name,
+ int32 index, char **path_buffer)
+{
+ status_t rc;
+ BEntry entry;
+ BPath path;
+ entry_ref ref;
+ BMessage *msg;
+
+ msg = (BMessage *) message;
+ rc = msg->FindRef (name, index, &ref);
+
+ if (rc != B_OK)
+ return 1;
+
+ rc = entry.SetTo (&ref, 0);
+
+ if (rc != B_OK)
+ return 1;
+
+ rc = entry.GetPath (&path);
+
+ if (rc != B_OK)
+ return 1;
+
+ *path_buffer = strdup (path.Path ());
+ return 0;
+}
+
+int
+be_get_message_data (void *message, const char *name,
+ int32 type_code, int32 index,
+ const void **buf_return,
+ ssize_t *size_return)
+{
+ BMessage *msg = (BMessage *) message;
+
+ return msg->FindData (name, type_code,
+ index, buf_return, size_return) != B_OK;
+}
haiku_write (APP_QUIT_REQUESTED_EVENT, &rq);
return 0;
}
-
- void
- RefsReceived (BMessage *msg)
- {
- struct haiku_refs_event rq;
- entry_ref ref;
- BEntry entry;
- BPath path;
- int32 cookie = 0;
- int32 x, y;
- void *window;
-
- if ((msg->FindPointer ("window", 0, &window) != B_OK)
- || (msg->FindInt32 ("x", 0, &x) != B_OK)
- || (msg->FindInt32 ("y", 0, &y) != B_OK))
- return;
-
- rq.window = window;
- rq.x = x;
- rq.y = y;
-
- while (msg->FindRef ("refs", cookie++, &ref) == B_OK)
- {
- if (entry.SetTo (&ref, 0) == B_OK
- && entry.GetPath (&path) == B_OK)
- {
- rq.ref = strdup (path.Path ());
- haiku_write (REFS_EVENT, &rq);
- }
- }
- }
};
class EmacsWindow : public BWindow
if (msg->WasDropped ())
{
- entry_ref ref;
BPoint whereto;
+ struct haiku_drag_and_drop_event rq;
- if (msg->FindRef ("refs", &ref) == B_OK)
+ if (msg->FindPoint ("_drop_point_", &whereto) == B_OK)
{
- msg->what = B_REFS_RECEIVED;
- msg->AddPointer ("window", this);
- if (msg->FindPoint ("_drop_point_", &whereto) == B_OK)
- {
- this->ConvertFromScreen (&whereto);
- msg->AddInt32 ("x", whereto.x);
- msg->AddInt32 ("y", whereto.y);
- }
- be_app->PostMessage (msg);
- msg->SendReply (B_OK);
+ this->ConvertFromScreen (&whereto);
+
+ rq.window = this;
+ rq.message = DetachCurrentMessage ();;
+ rq.x = whereto.x;
+ rq.y = whereto.y;
+
+ haiku_write (DRAG_AND_DROP_EVENT, &rq);
}
}
else if (msg->GetPointer ("menuptr"))
pthread_cond_signal (&w->menu_update_cv);
pthread_mutex_unlock (&w->menu_update_mutex);
}
+
+void
+BMessage_delete (void *message)
+{
+ delete (BMessage *) message;
+}
FILE_PANEL_EVENT,
MENU_BAR_HELP_EVENT,
ZOOM_EVENT,
- REFS_EVENT,
+ DRAG_AND_DROP_EVENT,
APP_QUIT_REQUESTED_EVENT,
DUMMY_EVENT,
MENU_BAR_LEFT
int height;
};
-struct haiku_refs_event
+struct haiku_drag_and_drop_event
{
void *window;
int x, y;
- /* Free this with free! */
- char *ref;
+ void *message;
};
struct haiku_app_quit_requested_event
extern void
BWindow_dimensions (void *window, int *width, int *height);
+ extern void
+ BMessage_delete (void *message);
+
#ifdef __cplusplus
extern void *
find_appropriate_view_for_draw (void *vw);
return value ? Qt : Qnil;
}
+/* Return the Lisp representation of MESSAGE.
+
+ It is an alist of strings, denoting message parameter names, to a
+ list the form (TYPE . (DATA ...)), where TYPE is an integer
+ denoting the system data type of DATA, and DATA is in the general
+ case a unibyte string.
+
+ If TYPE is a symbol instead of an integer, then DATA was specially
+ decoded. If TYPE is `ref', then DATA is the absolute file name of
+ a file, or nil if decoding the file name failed. If TYPE is
+ `string', then DATA is a unibyte string. If TYPE is `short', then
+ DATA is a 16-bit signed integer. If TYPE is `long', then DATA is a
+ 32-bit signed integer. If TYPE is `llong', then DATA is a 64-bit
+ signed integer. If TYPE is `byte' or `char', then DATA is an 8-bit
+ signed integer. If TYPE is `bool', then DATA is a boolean. */
+Lisp_Object
+haiku_message_to_lisp (void *message)
+{
+ Lisp_Object list = Qnil, tem, t1, t2;
+ const char *name;
+ char *pbuf;
+ const void *buf;
+ ssize_t buf_size;
+ int32 i, j, count, type_code;
+ int rc;
+
+ for (i = 0; !be_enum_message (message, &type_code, i,
+ &count, &name); ++i)
+ {
+ tem = Qnil;
+
+ for (j = 0; j < count; ++j)
+ {
+ rc = be_get_message_data (message, name,
+ type_code, j,
+ &buf, &buf_size);
+ if (rc)
+ emacs_abort ();
+
+ switch (type_code)
+ {
+ case 'BOOL':
+ t1 = (*(bool *) buf) ? Qt : Qnil;
+ break;
+
+ case 'RREF':
+ rc = be_get_refs_data (message, name,
+ j, &pbuf);
+
+ if (rc)
+ {
+ t1 = Qnil;
+ break;
+ }
+
+ if (!pbuf)
+ memory_full (SIZE_MAX);
+
+ t1 = build_string (pbuf);
+ free (pbuf);
+ break;
+
+ case 'SHRT':
+ t1 = make_fixnum (*(int16 *) buf);
+ break;
+
+ case 'LONG':
+ t1 = make_int (*(int32 *) buf);
+ break;
+
+ case 'LLNG':
+ t1 = make_int ((intmax_t) *(int64 *) buf);
+ break;
+
+ case 'BYTE':
+ case 'CHAR':
+ t1 = make_fixnum (*(int8 *) buf);
+ break;
+
+ default:
+ t1 = make_uninit_string (buf_size);
+ memcpy (SDATA (t1), buf, buf_size);
+ }
+
+ tem = Fcons (t1, tem);
+ }
+
+ switch (type_code)
+ {
+ case 'CSTR':
+ t2 = Qstring;
+ break;
+
+ case 'SHRT':
+ t2 = Qshort;
+ break;
+
+ case 'LONG':
+ t2 = Qlong;
+ break;
+
+ case 'LLNG':
+ t2 = Qllong;
+ break;
+
+ case 'BYTE':
+ t2 = Qbyte;
+ break;
+
+ case 'RREF':
+ t2 = Qref;
+ break;
+
+ case 'CHAR':
+ t2 = Qchar;
+ break;
+
+ case 'BOOL':
+ t2 = Qbool;
+ break;
+
+ default:
+ t2 = make_int (type_code);
+ }
+
+ tem = Fcons (t2, tem);
+ list = Fcons (Fcons (build_string_from_utf8 (name), tem), list);
+ }
+
+ return list;
+}
+
void
syms_of_haikuselect (void)
{
DEFSYM (QUTF8_STRING, "UTF8_STRING");
DEFSYM (Qforeign_selection, "foreign-selection");
DEFSYM (QTARGETS, "TARGETS");
+ DEFSYM (Qstring, "string");
+ DEFSYM (Qref, "ref");
+ DEFSYM (Qshort, "short");
+ DEFSYM (Qlong, "long");
+ DEFSYM (Qllong, "llong");
+ DEFSYM (Qbyte, "byte");
+ DEFSYM (Qchar, "char");
+ DEFSYM (Qbool, "bool");
defsubr (&Shaiku_selection_data);
defsubr (&Shaiku_selection_put);
#include <cstdio>
#endif
+#include <SupportDefs.h>
+
#ifdef __cplusplus
#include <stdio.h>
extern "C"
extern bool
BClipboard_owns_primary (void);
- extern bool
- BClipboard_owns_secondary (void);
+ extern bool BClipboard_owns_secondary (void);
/* Free the returned data. */
extern void BClipboard_free_data (void *ptr);
+
+ extern int be_enum_message (void *message, int32 *tc, int index,
+ int32 *count, const char **name_return);
+ extern int be_get_message_data (void *message, const char *name,
+ int32 type_code, int32 index,
+ const void **buf_return,
+ ssize_t *size_return);
+ extern int be_get_refs_data (void *message, const char *name,
+ int32 index, char **path_buffer);
#ifdef __cplusplus
};
#endif
haiku_make_fullscreen_consistent (f);
break;
}
- case REFS_EVENT:
+ case DRAG_AND_DROP_EVENT:
{
- struct haiku_refs_event *b = buf;
+ struct haiku_drag_and_drop_event *b = buf;
struct frame *f = haiku_window_to_frame (b->window);
if (!f)
{
- free (b->ref);
+ BMessage_delete (b->message);
continue;
}
inev.kind = DRAG_N_DROP_EVENT;
- inev.arg = build_string_from_utf8 (b->ref);
+ inev.arg = haiku_message_to_lisp (b->message);
XSETINT (inev.x, b->x);
XSETINT (inev.y, b->y);
XSETFRAME (inev.frame_or_window, f);
- /* There should be no problem with calling free here.
- free on Haiku is thread-safe. */
- free (b->ref);
+ BMessage_delete (b->message);
break;
}
case APP_QUIT_REQUESTED_EVENT:
extern void haiku_scroll_bar_remove (struct scroll_bar *bar);
extern void haiku_clear_under_internal_border (struct frame *f);
extern void haiku_set_name (struct frame *f, Lisp_Object name, bool explicit_p);
+extern Lisp_Object haiku_message_to_lisp (void *);
extern struct haiku_display_info *haiku_term_init (void);