mouse highlighting fixes. and cleanups. dropped CoolWidget mouse code in gnome version

This commit is contained in:
Paul Sheer 1998-12-17 04:05:13 +00:00
parent 0a301c466c
commit d5cb676e0b
6 changed files with 162 additions and 718 deletions

View File

@ -78,7 +78,7 @@ void edit_status (WEdit * edit)
widget_move (edit, edit->have_frame, edit->have_frame);
i = w > 24 ? 18 : w - 6;
i = i < 13 ? 13 : i;
sprintf (s, "%s", name_trunc (edit->filename ? edit->filename : "", i));
sprintf (s, "%s", (char *) name_trunc (edit->filename ? edit->filename : "", i));
i += strlen (s);
s[strlen (s)] = ' ';
t = w - 20;
@ -103,8 +103,10 @@ void rerender_text (CWidget * wdt);
#ifdef GTK
void edit_status (WEdit *edit)
void edit_status (WEdit * edit)
{
GtkEntry *entry;
GtkWidget *widget;
int w, i, t;
char id[33];
char s[160];
@ -127,8 +129,9 @@ void edit_status (WEdit *edit)
status_string (edit, s + i + 2, t, 0, FONT_MEAN_WIDTH);
}
s[w] = 0;
if (strcmp (s, GTK_LABEL(edit->widget->status)->label))
gtk_label_set (GTK_LABEL(edit->widget->status), s);
entry = GTK_ENTRY (edit->widget->status);
if (strcmp (s, gtk_entry_get_text (entry)))
gtk_entry_set_text (entry, s);
}
#else
@ -467,8 +470,6 @@ void render_edit_text (WEdit * edit, long start_row, long start_column, long end
#ifndef MIDNIGHT
static unsigned long prev_win = 0;
#endif
int fg, bg;
int force = edit->force;
long b;

View File

@ -25,10 +25,8 @@
#ifndef MIDNIGHT
#include <X11/Xmd.h> /* CARD32 */
#include <X11/Xatom.h>
#ifndef GTK
#include "app_glob.c"
#include "coollocal.h"
#endif
#include "editcmddef.h"
#include "mousemark.h"
#endif
@ -51,11 +49,7 @@ void edit_destroy_callback (CWidget * w)
CError ("Trying to destroy non-existing editor widget.\n");
}
#ifdef GTK
#else
void link_hscrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * xevent, CEvent * cwevent, int whichscrbutton);
#endif
/* returns the position in the edit buffer of a window click */
long edit_get_click_pos (WEdit * edit, int x, int y)
@ -83,7 +77,7 @@ void edit_translate_xy (int xs, int ys, int *x, int *y)
extern int just_dropped_something;
static void mouse_redraw (WEdit * edit, long click)
void mouse_redraw (WEdit * edit, long click)
{
edit->force |= REDRAW_PAGE | REDRAW_LINE;
edit_update_curs_row (edit);
@ -145,20 +139,7 @@ static void release_mark (WEdit * edit, XEvent * event)
edit_mark_cmd (edit, 1);
if (edit->mark1 != edit->mark2 && event) {
edit_get_selection (edit);
#ifdef GTK
{
#if 0
long start_mark = 0, end_mark = 0;
edit->widget->editable.has_selection = !eval_marks (edit, &start_mark, &end_mark);
edit->widget->editable.selection_start_pos = start_mark;
edit->widget->editable.selection_end_pos = end_mark;
if (edit->widget->editable.has_selection)
#endif
gtk_selection_owner_set (GTK_WIDGET (edit->widget), GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
}
#else
XSetSelectionOwner (CDisplay, XA_PRIMARY, CWindowOf (edit->widget), event->xbutton.time);
#endif
} else {
edit->widget->editable.has_selection = TRUE;
}
@ -211,7 +192,6 @@ char *filename_from_url (char *data, int size, int i)
static int insert_drop (WEdit * e, Window from, unsigned char *data, int size, int xs, int ys, Atom type, Atom action)
{
#ifndef GTK
long start_mark = 0, end_mark = 0;
int x, y;
@ -256,7 +236,6 @@ static int insert_drop (WEdit * e, Window from, unsigned char *data, int size, i
}
}
CExpose (e->widget->ident);
#endif
return 0;
}
@ -284,8 +263,6 @@ struct mouse_funcs edit_mouse_funcs =
mime_majors
};
#ifndef GTK
extern int option_editor_bg_normal;
void edit_tri_cursor (Window win);
@ -360,17 +337,6 @@ CWidget *CDrawEditor (const char *identifier, Window parent, int x, int y,
return w;
}
#endif
#ifdef GTK
void update_scroll_bars (WEdit * e)
{
}
#else
void update_scroll_bars (WEdit * e)
{
int i, x1, x2;
@ -412,8 +378,6 @@ void update_scroll_bars (WEdit * e)
}
}
#endif
void edit_mouse_mark (WEdit * edit, XEvent * event, int double_click)
{
edit_update_curs_row (edit);
@ -434,10 +398,6 @@ void edit_mouse_mark (WEdit * edit, XEvent * event, int double_click)
);
}
#ifdef GTK
#else
void link_scrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * xevent, CEvent * cwevent, int whichscrbutton)
{
int i, start_line;
@ -489,12 +449,6 @@ void link_scrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * x
}
}
#endif
#ifdef GTK
#else
void link_hscrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * xevent, CEvent * cwevent, int whichscrbutton)
{
int i, start_col;
@ -544,8 +498,6 @@ void link_hscrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent *
}
}
#endif
/*
This section comes from rxvt-2.21b1/src/screen.c by
Robert Nation <nation@rocket.sanders.lockheed.com> &
@ -597,7 +549,6 @@ void selection_send (XSelectionRequestEvent * rq)
/*{{{ paste selection */
#ifndef GTK
/*
* Respond to a notification that a primary selection has been sent
*/
@ -641,8 +592,6 @@ void selection_paste (WEdit * edit, Window win, unsigned prop, int delete)
edit->force |= REDRAW_COMPLETELY | REDRAW_LINE;
}
#endif
/*}}} */
void selection_clear (void)
@ -670,19 +619,8 @@ void edit_update_screen (WEdit * e)
/* pop all events for this window for internal handling */
if (e->force & (REDRAW_CHAR_ONLY | REDRAW_COMPLETELY)) {
edit_render_keypress (e);
#ifdef GTK
} else if (
#if 0
/* *** */
gtk_edit_key_pending () || gtk_edit_mouse_pending ()
#else
0
#endif
) {
#else
} else if (CCheckWindowEvent (e->widget->winid, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask, 0)
|| CKeyPending ()) {
#endif
e->force |= REDRAW_PAGE;
return;
} else {
@ -690,6 +628,7 @@ void edit_update_screen (WEdit * e)
}
}
extern int space_width;
#ifdef HAVE_DND
@ -796,8 +735,6 @@ void handle_client_message (CWidget * w, XEvent * xevent)
}
#endif
#ifndef GTK
int eh_editor (CWidget * w, XEvent * xevent, CEvent * cwevent)
{
WEdit *e = w->editor;
@ -909,8 +846,6 @@ int eh_editor (CWidget * w, XEvent * xevent, CEvent * cwevent)
return r;
}
#endif /* ! GTK */
#else
WEdit *wedit;

View File

@ -40,6 +40,7 @@
#define GDK_FONT_XFONT(font) (((GdkFontPrivate*) font)->xfont)
int edit_key_emulation = 0;
int column_highlighting = 0;
static GtkWidgetClass *parent_class = NULL;
@ -51,6 +52,7 @@ static void gtk_edit_set_position (GtkEditable *editable, gint position);
void edit_mouse_mark (WEdit * edit, XEvent * event, int double_click);
void edit_move_to_prev_col (WEdit * edit, long p);
int edit_load_file_from_filename (WEdit *edit, char *exp);
static void gtk_edit_set_selection (GtkEditable * editable, gint start, gint end);
guchar gtk_edit_font_width_per_char[256];
@ -298,11 +300,11 @@ static void gtk_edit_destroy (GtkObject * object)
gtk_timeout_remove (edit->timer);
edit->timer = 0;
}
if (edit->funcs) {
free (edit->funcs);
edit_clean (edit->editor);
if (edit->editor) {
free (edit->editor);
edit->editor = NULL;
}
edit_destroy_callback (edit);
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
@ -525,16 +527,84 @@ static gint
return FALSE;
}
static gint
gtk_edit_button_press_release (GtkWidget * widget,
GdkEventButton * event)
void edit_update_screen (WEdit * e)
{
if (!e)
return;
if (!e->force)
return;
edit_scroll_screen_over_cursor (e);
edit_update_curs_row (e);
edit_update_curs_col (e);
#if 0
update_scroll_bars (e);
#endif
edit_status (e);
if (e->force & REDRAW_COMPLETELY)
e->force |= REDRAW_PAGE;
/* pop all events for this window for internal handling */
if (e->force & (REDRAW_CHAR_ONLY | REDRAW_COMPLETELY)) {
edit_render_keypress (e);
#if 0
} else if (CCheckWindowEvent (e->widget->winid, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask, 0)
|| CKeyPending ()) {
e->force |= REDRAW_PAGE;
return;
#endif
} else {
edit_render_keypress (e);
}
}
void gtk_edit_mouse_redraw (WEdit * edit, long click)
{
edit->force |= REDRAW_PAGE | REDRAW_LINE;
edit_update_curs_row (edit);
edit_update_curs_col (edit);
edit->prev_col = edit_get_col (edit);
edit_update_screen (edit);
edit->search_start = click;
}
/* returns the position in the edit buffer of a window click */
static long edit_get_click_pos (WEdit * edit, int x, int y)
{
long click;
/* (1) goto to left margin */
click = edit_bol (edit, edit->curs1);
/* (1) move up or down */
if (y > (edit->curs_row + 1))
click = edit_move_forward (edit, click, y - (edit->curs_row + 1), 0);
if (y < (edit->curs_row + 1))
click = edit_move_backward (edit, click, (edit->curs_row + 1) - y);
/* (3) move right to x pos */
click = edit_move_forward3 (edit, click, x - edit->start_col - 1, 0);
return click;
}
static void edit_translate_xy (int xs, int ys, int *x, int *y)
{
*x = xs - EDIT_TEXT_HORIZONTAL_OFFSET;
*y = (ys - EDIT_TEXT_VERTICAL_OFFSET - option_text_line_spacing / 2 - 1) / FONT_PIX_PER_LINE + 1;
}
static gint gtk_edit_button_press_release (GtkWidget * widget,
GdkEventButton * event)
{
int double_click = 0;
XEvent xevent;
GtkEdit *edit;
GtkEditable *editable;
GtkEdit *edit;
WEdit *e;
static GdkAtom ctext_atom = GDK_NONE;
long start_mark = 0, end_mark = 0;
int x_text = 0, y_text = 0;
long mouse_pos;
static long button_down_pos;
static long dragging = 0;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_EDIT (widget), FALSE);
@ -544,45 +614,73 @@ static gint
ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
edit = GTK_EDIT (widget);
e = edit->editor;
editable = GTK_EDITABLE (widget);
if (!GTK_WIDGET_HAS_FOCUS (widget))
if (!(event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)))
gtk_widget_grab_focus (widget);
edit_translate_xy (event->x, event->y, &x_text, &y_text);
mouse_pos = edit_get_click_pos (e, x_text, y_text);
switch (event->type) {
case GDK_BUTTON_RELEASE:
if (!dragging)
return FALSE;
case GDK_MOTION_NOTIFY:
xevent.type = MotionNotify;
if (mouse_pos == button_down_pos)
return FALSE;
dragging = 1;
edit_cursor_move (e, mouse_pos - e->curs1);
gtk_edit_set_selection (GTK_EDITABLE (widget), mouse_pos, button_down_pos);
gtk_edit_mouse_redraw (e, mouse_pos);
break;
case GDK_BUTTON_PRESS:
xevent.type = ButtonPress;
dragging = 0;
if (event->button == 2) {
edit_cursor_move (e, mouse_pos - e->curs1);
editable->current_pos = mouse_pos;
gtk_selection_convert (GTK_WIDGET (edit), GDK_SELECTION_PRIMARY,
ctext_atom, event->time);
gtk_edit_mouse_redraw (e, mouse_pos);
editable->selection_start_pos = e->mark1;
editable->selection_end_pos = e->mark2;
return FALSE;
}
button_down_pos = mouse_pos;
#if 0
if (editable->has_selection)
if (mouse_pos >= editable->selection_start_pos
&& mouse_pos < editable->selection_end_pos)
gtk_edit_set_selection (GTK_EDITABLE (widget), mouse_pos, mouse_pos);
#endif
edit_cursor_move (e, mouse_pos - e->curs1);
gtk_edit_mouse_redraw (e, mouse_pos);
break;
case GDK_2BUTTON_PRESS:
xevent.type = ButtonPress;
double_click = 1;
break;
case GDK_BUTTON_RELEASE:
xevent.type = ButtonRelease;
dragging = 0;
edit_cursor_move (e, mouse_pos - e->curs1);
edit_right_word_move (e);
mouse_pos = e->curs1;
edit_left_word_move (e);
button_down_pos = e->curs1;
gtk_edit_set_selection (GTK_EDITABLE (widget), mouse_pos, button_down_pos);
gtk_edit_mouse_redraw (e, mouse_pos);
break;
case GDK_3BUTTON_PRESS:
dragging = 0;
mouse_pos = edit_bol (e, mouse_pos);
edit_cursor_move (e, mouse_pos - e->curs1);
button_down_pos = edit_eol (e, mouse_pos) + 1;
gtk_edit_set_selection (GTK_EDITABLE (widget), mouse_pos, button_down_pos);
gtk_edit_mouse_redraw (e, mouse_pos);
break;
default:
return FALSE;
dragging = 0;
break;
}
xevent.xbutton.window = (guint32) event->window;
xevent.xbutton.x = event->x;
xevent.xbutton.y = event->y;
xevent.xbutton.state = event->state;
edit_mouse_mark (edit->editor, &xevent, double_click);
editable->current_pos = edit->editor->curs1;
editable->has_selection = !eval_marks (edit->editor, &start_mark, &end_mark);
editable->selection_start_pos = start_mark;
editable->selection_end_pos = end_mark;
if (event->type == GDK_BUTTON_PRESS && event->button == 2)
gtk_selection_convert (GTK_WIDGET (edit), GDK_SELECTION_PRIMARY,
ctext_atom, event->time);
editable->current_pos = e->curs1;
return FALSE;
}
@ -638,22 +736,19 @@ short key_sym_mod (gint key, gint state)
return key;
}
static gint
gtk_edit_key_press (GtkWidget * widget,
GdkEventKey * event)
static gint gtk_edit_key_press (GtkWidget * widget, GdkEventKey * event)
{
GtkEdit *edit;
GtkEditable *editable;
GtkEdit *edit;
WEdit *e;
gint command = 0, insert = -1, r = 0;
guint key, state;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_EDIT (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
edit = GTK_EDIT (widget);
editable = GTK_EDITABLE (widget);
e = edit->editor;
if (!edit_translate_key (0, event->keyval, event->state, &command, &insert)) {
return FALSE;
}
@ -661,17 +756,20 @@ static gint
state = event->state;
if (!command && insert < 0) { /* no translation took place, so lets see if we have a macro */
if ((key == GDK_r || key == GDK_R) && (state & ControlMask)) {
command = edit->editor->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
command = e->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
} else {
command = key_sym_mod (key, state);
if (command > 0)
command = CK_Macro (command);
}
}
r = edit_execute_key_command (edit->editor, command, insert);
r = edit_execute_key_command (e, command, insert);
if (r)
edit_update_screen (edit->editor);
edit_update_screen (e);
editable->selection_start_pos = e->mark1;
editable->selection_end_pos = ((e->mark2 < 0) ? e->curs1 : e->mark2);
editable->has_selection = editable->selection_start_pos != editable->selection_end_pos;
editable->current_pos = e->curs1;
return r;
}
@ -729,26 +827,15 @@ static void gtk_edit_set_selection (GtkEditable * editable,
gint end)
{
GtkEdit *edit = GTK_EDIT (editable);
guint start1, end1, start2, end2;
WEdit *e;
e = edit->editor;
if (end < 0)
end = edit->editor->last_byte;
start1 = MIN (start, end);
end1 = MAX (start, end);
start2 = MIN (editable->selection_start_pos, editable->selection_end_pos);
end2 = MAX (editable->selection_start_pos, editable->selection_end_pos);
if (start2 < start1) {
guint tmp;
tmp = start1;
start1 = start2;
start2 = tmp;
tmp = end1;
end1 = end2;
end2 = tmp;
}
editable->selection_start_pos = start;
editable->selection_end_pos = end;
editable->has_selection = TRUE;
return;
editable->selection_start_pos = e->mark1 = MIN (start, end);
editable->selection_end_pos = e->mark2 = MAX (start, end);
editable->has_selection = (e->mark2 != e->mark1);
gtk_edit_mouse_redraw (e, e->curs1);
gtk_editable_claim_selection (editable, TRUE, GDK_CURRENT_TIME);
}
static void gtk_edit_insert_text (GtkEditable * editable,
@ -818,8 +905,6 @@ static void gtk_edit_class_init (GtkEditClass * class)
get_home_dir ();
}
extern struct mouse_funcs edit_mouse_funcs;
static void gtk_edit_init (GtkEdit * edit)
{
static made_directory = 0;
@ -833,7 +918,6 @@ static void gtk_edit_init (GtkEdit * edit)
edit->menubar = 0;
edit->status = 0;
edit->options = 0;
edit->funcs = mouse_funcs_new (edit->editor, &edit_mouse_funcs);
gtk_edit_configure_font_dimensions (edit);
@ -1261,7 +1345,7 @@ int edit (const char *file, int line)
{
{
GNOME_APP_UI_ITEM,
N_ ("About..."), N_ ("Info about GNOME hello"),
N_ ("About..."), N_ ("Info about Mcedit"),
about_cb, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_ABOUT,
0, (GdkModifierType) 0, NULL
@ -1283,7 +1367,8 @@ int edit (const char *file, int line)
};
gtk_widget_realize (app);
statusbar = gtk_label_new (file ? file : "<no-filename>");
statusbar = gtk_entry_new ();
gtk_entry_set_editable (GTK_ENTRY (statusbar), 0);
gtk_widget_set_usize (app, 400, 400);
gnome_app_create_menus (GNOME_APP (app), main_menu);
gnome_app_set_contents (GNOME_APP (app), edit);
@ -1303,7 +1388,7 @@ int edit (const char *file, int line)
return 1;
}
gtk_edit_set_cursor_line (edit, line);
gtk_widget_show (app);
gtk_widget_show_all (app);
gtk_widget_grab_focus (edit);
}
return 0;

View File

@ -58,7 +58,6 @@ struct _GtkEdit
void (*destroy_me) (void *);
void *destroy_me_user_data;
struct editor_widget *editor;
struct mouse_funcs *funcs;
gulong options;
gint timer;
};

View File

@ -1,507 +0,0 @@
/* mousemark.c - mouse stuff marking dragging
Copyright (C) 1996, 1997 the Free Software Foundation
Authors: 1996, 1997 Paul Sheer
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#ifndef GTK
#include "coolwidget.h"
#endif
int just_dropped_something = 0;
#include "edit.h"
#include <X11/Xmd.h>
#include <X11/Xatom.h>
#ifndef GTK
#include "app_glob.c"
#include "coollocal.h"
#endif
#include "editcmddef.h"
#include "xdnd.h"
#ifdef GTK
#include "src/mad.h"
#else
#include "mad.h"
#endif
#ifndef HAVE_DND
Atom **xdnd_typelist_send = 0;
Atom **xdnd_typelist_receive = 0;
#define NUM_SIMPLE_TYPES 10
/* each entry is listed in order of what we would like the RECEIVE */
static char *mime_type_send[NUM_SIMPLE_TYPES][10] =
{
{0}, /* DndUnknown 0 */
{0}, /* DndRawData 1 */
{"url/url", "text/plain", 0}, /* DndFile 2 (input widget) */
{"text/plain", "text/uri-list", 0}, /* DndFiles 3 (fielded text box) */
{"text/plain", "application/octet-stream", 0}, /* DndText 4 (editor widget) */
/* don't use these: */
{0}, /* DndLink 5 */
{0}, /* DndDir 6 */
{0}, /* DndExe 7 */
{0}, /* DndURL 8 */
{0}, /* DndMIME 9 */
};
static char *mime_type_recieve[NUM_SIMPLE_TYPES][10] =
{
{0}, /* DndUnknown 0 */
{0}, /* DndRawData 1 */
{"url/url", "text/uri-list", "text/plain", 0}, /* DndFile 2 (input widget) */
{0}, /* DndFiles 3 */
{"url/url", "text/plain", "application/octet-stream", "text/uri-list", 0}, /* DndText 4 (editor widget) */
/* don't use these: */
{0}, /* DndLink 5 */
{0}, /* DndDir 6 */
{0}, /* DndExe 7 */
{0}, /* DndURL 8 */
{0}, /* DndMIME 9 */
};
#ifndef GTK
static char dnd_directory[MAX_PATH_LEN] = "/";
char *striptrailing (char *s, int c)
{
int i;
i = strlen (s) - 1;
while (i >= 0) {
if (s[i] == c) {
s[i--] = 0;
continue;
}
break;
}
return s;
}
/* return the prepending directory (see CDndFileList() below) */
char *CDndDirectory (void)
{
return dnd_directory;
}
/*
Sets the directory, must be a null terminated complete path.
Strips trailing slashes.
*/
void CSetDndDirectory (char *d)
{
if (!d)
return;
strcpy (dnd_directory, d);
striptrailing (dnd_directory, '/');
if (*dnd_directory)
return;
*dnd_directory = '/';
}
/*
Takes a newline seperated list of files,
returns a newline seperated list of complete `file:' path names
by prepending dnd_directory to each file name.
returns 0 if no files in list.
result must always be free'd.
returns l as the total length of data.
returns num_files as the number of files in the list.
Alters t
*/
char *CDndFileList (char *t, int *l, int *num_files)
{
char *p, *q, *r, *result;
int i, len, done = 0;
/* strip leading newlines */
while (*t == '\n')
t++;
/* strip trailing newlines */
striptrailing (t, '\n');
if (!*t)
return 0;
/* count files */
for (i = 1, p = t; *p; p++)
if (*p == '\n')
i++;
*num_files = i;
len = (unsigned long) p - (unsigned long) t;
result = CMalloc ((strlen (dnd_directory) + strlen ("file:") + 2) * i + len + 2);
r = result;
p = t;
while (!done) {
q = strchr (p, '\n');
if (q)
*q = 0;
else
done = 1;
strcpy (r, "file:");
if (*p != '/') {
strcat (r, dnd_directory);
strcat (r, "/");
}
strcat (r, p);
r += strlen (r);
*r++ = '\n';
p = ++q;
}
*r = 0;
*l = (unsigned long) r - (unsigned long) result;
return result;
}
Window get_focus_border_widget (void);
static void widget_apply_leave (DndClass * dnd, Window widgets_window)
{
CWidget *w;
w = CWidgetOfWindow (widgets_window);
if (get_focus_border_widget () == widgets_window)
destroy_focus_border ();
if (w)
CExpose (w->ident);
}
static int widget_insert_drop (DndClass * dnd, unsigned char *data, int length, int remaining, Window into, Window from, Atom type)
{
CWidget *w;
char *p;
w = CWidgetOfWindow (into);
if (!w)
return 1;
if (*w->funcs->insert_drop) {
int r;
Window child_return;
int xd, yd;
if (!dnd->user_hook1)
dnd->user_hook2 = dnd->user_hook1 = CMalloc (length + remaining + 1);
memcpy (dnd->user_hook2, data, length);
p = dnd->user_hook2;
p += length; /* avoids ansi warning */
dnd->user_hook2 = p;
if (remaining)
return 0;
XTranslateCoordinates (CDisplay, CRoot, into, dnd->x, dnd->y, &xd, &yd, &child_return);
r = (*w->funcs->insert_drop) (w->funcs->data, from, dnd->user_hook1, (unsigned long) dnd->user_hook2 - (unsigned long) dnd->user_hook1, xd, yd, type, dnd->supported_action);
free (dnd->user_hook1);
dnd->user_hook1 = dnd->user_hook2 = 0;
if (get_focus_border_widget () == into)
destroy_focus_border ();
CExpose (w->ident);
return r;
}
return 1;
}
static int array_length (Atom * a)
{
int n;
for (n = 0; a[n]; n++);
return n;
}
static int widget_apply_position (DndClass * dnd, Window widgets_window, Window from,
Atom action, int x, int y, Time t, Atom * typelist,
int *want_position, Atom * supported_action, Atom * desired_type,
XRectangle * rectangle)
{
CWidget *w;
Window child_return;
int xt, yt;
int xd, yd;
long click;
int i, j;
Atom result = 0;
w = CWidgetOfWindow (widgets_window);
if (!w)
return 0;
/* input widgets can't drop to themselves :-( */
if (w->kind == C_TEXTINPUT_WIDGET && widgets_window == from)
return 0;
/* look up mime types from my own list of supported types */
for (j = 0; xdnd_typelist_receive[w->funcs->types][j]; j++) {
for (i = 0; typelist[i]; i++) {
if (typelist[i] == xdnd_typelist_receive[w->funcs->types][j]) {
result = typelist[i];
break;
}
}
if (result)
break;
}
if (!result && w->funcs->mime_majors) {
char **names_return;
names_return = CMalloc ((array_length (typelist) + 1) * sizeof (char *));
if (XGetAtomNames (CDisplay, typelist, array_length (typelist), names_return)) {
for (i = 0; i < array_length (typelist); i++) {
for (j = 0; w->funcs->mime_majors[j]; j++) {
if (!strncmp (w->funcs->mime_majors[j], names_return[i], strlen (w->funcs->mime_majors[j]))) {
result = typelist[i];
break;
}
}
if (result)
break;
}
}
}
/* not supported, so return false */
if (!result)
return 0;
XTranslateCoordinates (CDisplay, CRoot, widgets_window, x, y, &xd, &yd, &child_return);
if (xd < 0 || yd < 0 || xd >= CWidthOf (w) || yd >= CHeightOf (w))
return 0;
if (w->funcs->xy && w->funcs->cp && w->funcs->move) {
(*w->funcs->xy) (xd, yd, &xt, &yt);
click = (*w->funcs->cp) (w->funcs->data, xt, yt);
if (w->funcs->fin_mark)
(*w->funcs->fin_mark) (w->funcs->data);
if (w->funcs->move)
(*w->funcs->move) (w->funcs->data, click, yt);
if (w->funcs->redraw)
(*w->funcs->redraw) (w->funcs->data, click);
}
/* we want more position messages */
*want_position = 1;
/* we only support copy and move */
if (action == dnd->XdndActionMove) {
*supported_action = dnd->XdndActionMove;
} else {
*supported_action = dnd->XdndActionCopy;
}
*desired_type = result;
rectangle->x = x;
rectangle->y = y;
rectangle->width = rectangle->height = 0;
if (get_focus_border_widget () != widgets_window) {
destroy_focus_border ();
create_focus_border (w, 4);
}
CExpose (w->ident);
return 1;
}
static void widget_get_data (DndClass * dnd, Window window, unsigned char **data, int *length, Atom type)
{
int t = DndText;
long start_mark, end_mark;
CWidget *w;
w = CWidgetOfWindow (window);
if (!w) {
return;
}
if (!w->funcs)
return;
if ((*w->funcs->marks) (w->funcs->data, &start_mark, &end_mark)) {
return;
}
if (type == XInternAtom (dnd->display, "url/url", False))
t = DndFile;
else if (type == XInternAtom (dnd->display, "text/uri-list", False))
t = DndFiles;
*data = (unsigned char *) (*w->funcs->get_block) (w->funcs->data, start_mark, end_mark, &t, length);
}
static int widget_exists (DndClass * dnd, Window window)
{
return (CWidgetOfWindow (window) != 0);
}
static void handle_expose_events (DndClass * dnd, XEvent * xevent)
{
if (!xevent->xexpose.count)
render_focus_border (xevent->xexpose.window);
return;
}
void mouse_init (void)
{
CDndClass->handle_expose_events = handle_expose_events;
CDndClass->widget_insert_drop = widget_insert_drop;
CDndClass->widget_exists = widget_exists;
CDndClass->widget_apply_position = widget_apply_position;
CDndClass->widget_get_data = widget_get_data;
CDndClass->widget_apply_leave = widget_apply_leave;
CDndClass->options |= XDND_OPTION_NO_HYSTERESIS;
CDndClass->user_hook1 = CDndClass->user_hook2 = 0;
if (!xdnd_typelist_receive) {
int i;
xdnd_typelist_receive = malloc ((NUM_SIMPLE_TYPES + 1) * sizeof (Atom *));
xdnd_typelist_send = malloc ((NUM_SIMPLE_TYPES + 1) * sizeof (Atom *));
for (i = 0; i < NUM_SIMPLE_TYPES; i++) {
int j;
xdnd_typelist_receive[i] = CMalloc (32 * sizeof (Atom));
for (j = 0; mime_type_recieve[i][j]; j++) {
xdnd_typelist_receive[i][j] = XInternAtom (CDndClass->display, mime_type_recieve[i][j], False);
xdnd_typelist_receive[i][j + 1] = 0;
}
xdnd_typelist_receive[i + 1] = 0;
xdnd_typelist_send[i] = CMalloc (32 * sizeof (Atom));
for (j = 0; mime_type_send[i][j]; j++) {
xdnd_typelist_send[i][j] = XInternAtom (CDndClass->display, mime_type_send[i][j], False);
xdnd_typelist_send[i][j + 1] = 0;
}
xdnd_typelist_send[i + 1] = 0;
}
}
}
void mouse_shut (void)
{
if (xdnd_typelist_receive) {
int i;
for (i = 0; xdnd_typelist_send[i]; i++)
free (xdnd_typelist_send[i]);
free (xdnd_typelist_send);
xdnd_typelist_send = 0;
for (i = 0; xdnd_typelist_receive[i]; i++)
free (xdnd_typelist_receive[i]);
free (xdnd_typelist_receive);
xdnd_typelist_receive = 0;
}
}
#endif /* !GTK */
struct mouse_funcs *mouse_funcs_new (void *data, struct mouse_funcs *m)
{
struct mouse_funcs *p;
p = CMalloc (sizeof (*m));
memcpy (p, m, sizeof (*m));
p->data = data;
return p;
}
#endif /* HAVE_DND */
void mouse_mark (XEvent * event, int double_click, struct mouse_funcs *funcs)
{
void *data;
static unsigned long win_press = 0;
static int state = 0; /* 0 = button up, 1 = button pressed, 2 = button pressed and dragging */
static int x_last, y_last;
long click;
data = funcs->data;
if (event->type == ButtonPress) {
long start_mark, end_mark;
state = 1;
win_press = (unsigned long) event->xbutton.window;
(*funcs->xy) (event->xbutton.x, event->xbutton.y, &x_last, &y_last);
click = (*funcs->cp) (data, x_last, y_last);
if (!(*funcs->marks) (data, &start_mark, &end_mark)) {
if ((*funcs->range) (data, start_mark, end_mark, click)) { /* if clicked on highlighted text */
unsigned char *t;
int l;
#ifdef HAVE_DND
int type;
t = (unsigned char *) (*funcs->get_block) (data, start_mark, end_mark, &type, &l);
if (t) {
just_dropped_something = 1;
CDrag (event->xbutton.window, type, t, l, event->xbutton.button == Button1 ? Button1Mask : 0);
free (t);
}
#else
#ifndef GTK
/* this is just to get the type which depends on the number of lines selected for
the fileselection box: */
t = (unsigned char *) (*funcs->get_block) (data, start_mark, end_mark, &funcs->types, &l);
if (t) {
free (t);
if (xdnd_drag (CDndClass, event->xbutton.window,
event->xbutton.button == Button1 ? CDndClass->XdndActionCopy : CDndClass->XdndActionMove,
xdnd_typelist_send[funcs->types]) == CDndClass->XdndActionMove) {
if (funcs->delete_block)
(*funcs->delete_block) (data);
}
}
#endif
#endif
if (funcs->fin_mark)
(*funcs->fin_mark) (data);
return;
}
}
just_dropped_something = 0;
if (funcs->fin_mark)
(*funcs->fin_mark) (data);
(*funcs->move) (data, click, y_last);
if (double_click && funcs->dclick) {
(*funcs->dclick) (data, event);
state = 0;
}
if (funcs->redraw)
(*funcs->redraw) (data, click);
} else if (event->type == ButtonRelease && state > 0 && win_press == (unsigned long) event->xbutton.window && !double_click) {
int x, y;
long start_mark, end_mark;
(*funcs->xy) (event->xbutton.x, event->xbutton.y, &x, &y);
click = (*funcs->cp) (data, x, y);
(*funcs->move) (data, click, y);
if (state == 2)
goto unhighlight;
if (!(*funcs->marks) (data, &start_mark, &end_mark)) {
if ((*funcs->range) (data, start_mark, end_mark, click)) { /* if clicked on highlighted text */
unhighlight:
if (funcs->release_mark)
(*funcs->release_mark) (data, event);
}
}
state = 0;
if (funcs->redraw)
(*funcs->redraw) (data, click);
} else if (event->type == MotionNotify && state > 0 && win_press == (unsigned long) event->xbutton.window && event->xbutton.state) {
int x, y;
if (!event->xmotion.state)
return;
(*funcs->xy) (event->xbutton.x, event->xbutton.y, &x, &y);
if (x == x_last && y == y_last && state == 1)
return;
click = (*funcs->cp) (data, x, y);
if (state == 1) {
state = 2;
if (funcs->move_mark)
(funcs->move_mark) (data);
}
(*funcs->move) (data, click, y);
if (funcs->motion)
(*funcs->motion) (data, click);
if (funcs->redraw)
(*funcs->redraw) (data, click);
}
}

View File

@ -1,69 +0,0 @@
/* Copyright (C) 1996, 1997 the Free Software Foundation
Authors: 1996, 1997 Paul Sheer
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _MOUSE_MARK
#define _MOUSE_MARK
/* mouse_mark.h */
struct mouse_funcs {
void *data;
void (*xy) (int, int, int *, int *);
/* (row, pixel-x-pos) from click pos (x,y) */
long (*cp) (void *, int, int); /* get buffer offset from (row, pixel-x-pos) */
int (*marks) (void *, long *, long *);
/* get mark start and end */
int (*range) (void *, long, long, long);
/* is click between marks? */
void (*fin_mark) (void *); /* set marks to not-moving mode (optional) */
void (*move_mark) (void *); /* set marks to moving mode (optional) */
void (*release_mark) (void *, XEvent *);
/* set marks when button is release.
possibly sets selection owner (could be
same as fin_mark) (optional) */
char * (*get_block) (void *, long, long, int *, int *);
/* return block from between marks,
result is free'd by mouse_mark
int *, int * is Dnd type, length */
void (*move) (void *, long, int); /* move cursor, int is row if needed */
void (*motion) (void *, long); /* move second mark position */
void (*dclick) (void *, XEvent *); /* called on double click (optional) */
void (*redraw) (void *, long);/* called before exit, passing mouse
pos in buffer (optional) */
int (*insert_drop) (void *, Window, unsigned char *, int, int, int, Atom, Atom);
void (*delete_block) (void *);
/* this is one of the old dnd types. these are our preference
for drag between cooledits */
int types;
/* anything else that the widget can recieve eg {"text", "video"} */
char **mime_majors;
};
void mouse_mark (XEvent * event, int double_click, struct mouse_funcs *funcs);
struct mouse_funcs *mouse_funcs_new (void *data, struct mouse_funcs *m);
void mouse_shut (void);
void mouse_init (void);
extern Atom **xdnd_typelist_receive;
extern Atom **xdnd_typelist_send;
#endif