1 /* editor initialisation and callback handler.
3 Copyright (C) 1996, 1997 the Free Software Foundation
5 Authors: 1996, 1997 Paul Sheer
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 #include <X11/Xmd.h> /* CARD32 */
28 #include <X11/Xatom.h>
30 #include "coollocal.h"
31 #include "editcmddef.h"
32 #include "mousemark.h"
34 #if defined (HAVE_MAD) && ! defined (MIDNIGHT) && ! defined (GTK)
40 extern int EditExposeRedraw
;
43 void edit_destroy_callback (CWidget
* w
)
46 edit_clean (w
->editor
);
52 CError ("Trying to destroy non-existing editor widget.\n");
55 void link_hscrollbar_to_editor (CWidget
* scrollbar
, CWidget
* editor
, XEvent
* xevent
, CEvent
* cwevent
, int whichscrbutton
);
57 /* returns the position in the edit buffer of a window click */
58 long edit_get_click_pos (WEdit
* edit
, int x
, int y
)
61 /* (1) goto to left margin */
62 click
= edit_bol (edit
, edit
->curs1
);
64 /* (1) move up or down */
65 if (y
> (edit
->curs_row
+ 1))
66 click
= edit_move_forward (edit
, click
, y
- (edit
->curs_row
+ 1), 0);
67 if (y
< (edit
->curs_row
+ 1))
68 click
= edit_move_backward (edit
, click
, (edit
->curs_row
+ 1) - y
);
70 /* (3) move right to x pos */
71 click
= edit_move_forward3 (edit
, click
, x
- edit
->start_col
- 1, 0);
75 void edit_translate_xy (int xs
, int ys
, int *x
, int *y
)
77 *x
= xs
- EDIT_TEXT_HORIZONTAL_OFFSET
;
78 *y
= (ys
- EDIT_TEXT_VERTICAL_OFFSET
- option_text_line_spacing
/ 2 - 1) / FONT_PIX_PER_LINE
+ 1;
81 extern int just_dropped_something
;
83 void mouse_redraw (WEdit
* edit
, long click
)
85 edit
->force
|= REDRAW_PAGE
| REDRAW_LINE
;
86 edit_update_curs_row (edit
);
87 edit_update_curs_col (edit
);
88 edit
->prev_col
= edit_get_col (edit
);
89 edit_update_screen (edit
);
90 edit
->search_start
= click
;
93 static void xy (int x
, int y
, int *x_return
, int *y_return
)
95 edit_translate_xy (x
, y
, x_return
, y_return
);
98 static long cp (WEdit
*edit
, int x
, int y
)
100 return edit_get_click_pos (edit
, x
, y
);
103 /* return 1 if not marked */
104 static int marks (WEdit
* edit
, long *start
, long *end
)
106 return eval_marks (edit
, start
, end
);
109 int column_highlighting
= 0;
111 static int erange (WEdit
* edit
, long start
, long end
, int click
)
113 if (column_highlighting
) {
115 x
= edit_move_forward3 (edit
, edit_bol (edit
, click
), 0, click
);
116 if ((x
>= edit
->column1
&& x
< edit
->column2
)
117 || (x
> edit
->column2
&& x
<= edit
->column1
))
118 return (start
<= click
&& click
< end
);
122 return (start
<= click
&& click
< end
);
125 static void fin_mark (WEdit
*edit
)
128 edit_mark_cmd (edit
, 0);
131 static void move_mark (WEdit
*edit
)
133 edit_mark_cmd (edit
, 1);
134 edit_mark_cmd (edit
, 0);
137 static void release_mark (WEdit
* edit
, XEvent
* event
)
140 edit_mark_cmd (edit
, 0);
142 edit_mark_cmd (edit
, 1);
143 if (edit
->mark1
!= edit
->mark2
&& event
) {
144 edit_get_selection (edit
);
145 XSetSelectionOwner (CDisplay
, XA_PRIMARY
, CWindowOf (edit
->widget
), event
->xbutton
.time
);
149 edit
->widget
->editable
.has_selection
= TRUE
;
154 static char *get_block (WEdit
* edit
, long start_mark
, long end_mark
, int *type
, int *l
)
157 t
= (char *) edit_get_block (edit
, start_mark
, end_mark
, l
);
159 *type
= DndRawData
; /* if there are nulls in the data, send as raw */
161 *type
= DndText
; /* else send as text */
165 static void move (WEdit
*edit
, long click
, int y
)
167 edit_cursor_move (edit
, click
- edit
->curs1
);
170 static void dclick (WEdit
*edit
, XEvent
*event
)
172 edit_mark_cmd (edit
, 1);
173 edit_right_word_move (edit
, 1);
174 edit_mark_cmd (edit
, 0);
175 edit_left_word_move (edit
, 1);
176 release_mark (edit
, event
);
179 static void redraw (WEdit
*edit
, long click
)
181 mouse_redraw (edit
, click
);
184 void edit_insert_column_of_text (WEdit
* edit
, unsigned char *data
, int size
, int width
);
186 /* strips out the first i chars and returns a null terminated string, result must be free'd */
187 char *filename_from_url (char *data
, int size
, int i
)
191 for (p
= data
+ i
; (unsigned long) p
- (unsigned long) data
< size
&& *p
&& *p
!= '\n'; p
++);
192 l
= (unsigned long) p
- (unsigned long) data
- i
;
194 memcpy (f
, data
+ i
, l
);
199 static int insert_drop (WEdit
* e
, Window from
, unsigned char *data
, int size
, int xs
, int ys
, Atom type
, Atom action
)
201 long start_mark
= 0, end_mark
= 0;
204 edit_translate_xy (xs
, ys
, &x
, &y
);
205 /* musn't be able to drop into a block, otherwise a single click will copy a block: */
206 if (eval_marks (e
, &start_mark
, &end_mark
))
208 if (start_mark
> e
->curs1
|| e
->curs1
>= end_mark
)
210 if (column_highlighting
) {
211 if (!((x
>= e
->column1
&& x
< e
->column2
)
212 || (x
> e
->column2
&& x
<= e
->column1
)))
217 if (from
== e
->widget
->winid
&& action
== CDndClass
->XdndActionMove
) {
218 edit_block_move_cmd (e
);
219 edit_mark_cmd (e
, 1);
221 } else if (from
== e
->widget
->winid
) {
222 edit_block_copy_cmd (e
);
224 } else { /* data from another widget, or from another application */
225 edit_push_action (e
, KEY_PRESS
+ e
->start_display
);
226 if (type
== XInternAtom (CDisplay
, "url/url", False
)) {
227 if (!strncmp ((char *) data
, "file:/", 6)) {
229 edit_insert_file (e
, f
= filename_from_url ((char *) data
, size
, strlen ("file:")));
233 edit_insert_ahead (e
, data
[size
]);
236 if (column_highlighting
) {
237 edit_insert_column_of_text (e
, data
, size
, abs (e
->column2
- e
->column1
));
240 edit_insert_ahead (e
, data
[size
]);
244 CExpose (e
->widget
->ident
);
248 static char *mime_majors
[2] =
251 struct mouse_funcs edit_mouse_funcs
=
254 (void (*)(int, int, int *, int *)) xy
,
255 (long (*)(void *, int, int)) cp
,
256 (int (*)(void *, long *, long *)) marks
,
257 (int (*)(void *, long, long, long)) erange
,
258 (void (*)(void *)) fin_mark
,
259 (void (*)(void *)) move_mark
,
260 (void (*)(void *, XEvent
*)) release_mark
,
261 (char *(*)(void *, long, long, int *, int *)) get_block
,
262 (void (*)(void *, long, int)) move
,
264 (void (*)(void *, XEvent
*)) dclick
,
265 (void (*)(void *, long)) redraw
,
266 (int (*)(void *, Window
, unsigned char *, int, int, int, Atom
, Atom
)) insert_drop
,
267 (void (*)(void *)) edit_block_delete
,
272 static void render_book_marks (CWidget
*w
);
273 extern int option_editor_bg_normal
;
274 void edit_tri_cursor (Window win
);
276 /* starting_directory is for the filebrowser */
277 CWidget
*CDrawEditor (const char *identifier
, Window parent
, int x
, int y
,
278 int width
, int height
, const char *text
, const char *filename
,
279 const char *starting_directory
, unsigned int options
, unsigned long text_size
)
281 static int made_directory
= 0;
282 int extra_space_for_hscroll
= 0;
286 if (options
& EDITOR_HORIZ_SCROLL
)
287 extra_space_for_hscroll
= 8;
289 wedit
= w
= CSetupWidget (identifier
, parent
, x
, y
,
290 width
+ EDIT_FRAME_W
, height
+ EDIT_FRAME_H
, C_EDITOR_WIDGET
,
291 ExposureMask
| ButtonPressMask
| ButtonReleaseMask
| \
292 KeyPressMask
| KeyReleaseMask
| ButtonMotionMask
| \
293 PropertyChangeMask
| StructureNotifyMask
| \
294 EnterWindowMask
| LeaveWindowMask
, color_palette (option_editor_bg_normal
), 1);
296 xdnd_set_dnd_aware (CDndClass
, w
->winid
, 0);
297 xdnd_set_type_list (CDndClass
, w
->winid
, xdnd_typelist_send
[DndText
]);
299 edit_tri_cursor (w
->winid
);
300 w
->options
= options
| WIDGET_TAKES_SELECTION
;
302 w
->destroy
= edit_destroy_callback
;
304 w
->label
= (char *) strdup (filename
);
306 w
->label
= (char *) strdup ("");
308 if (!made_directory
) {
309 mkdir (catstrs (home_dir
, EDIT_DIR
, 0), 0700);
312 e
= w
->editor
= CMalloc (sizeof (WEdit
));
313 w
->funcs
= mouse_funcs_new (w
->editor
, &edit_mouse_funcs
);
316 /* Not essential to translate */
317 CError (_ ("Error initialising editor.\n"));
320 w
->editor
->widget
= w
;
321 w
->editor
= edit_init (e
, height
/ FONT_PIX_PER_LINE
, width
/ FONT_MEAN_WIDTH
, filename
, text
, starting_directory
, text_size
);
322 w
->funcs
->data
= (void *) w
->editor
;
325 CDestroyWidget (w
->ident
);
331 set_hint_pos (x
+ width
+ EDIT_FRAME_W
+ WIDGET_SPACING
, y
+ height
+ EDIT_FRAME_H
+ WIDGET_SPACING
+ extra_space_for_hscroll
);
332 if (extra_space_for_hscroll
) {
333 w
->hori_scrollbar
= CDrawHorizontalScrollbar (catstrs (identifier
, ".hsc", 0), parent
,
334 x
, y
+ height
+ EDIT_FRAME_H
, width
+ EDIT_FRAME_W
, 12, 0, 0);
335 CSetScrollbarCallback (w
->hori_scrollbar
->ident
, w
->ident
, link_hscrollbar_to_editor
);
337 if (!(options
& EDITOR_NO_TEXT
))
338 CDrawStatus (catstrs (identifier
, ".text", 0), parent
, x
, y
+ height
+ 3 + EDIT_FRAME_H
+ WIDGET_SPACING
+ extra_space_for_hscroll
, width
+ EDIT_FRAME_W
, e
->filename
);
339 if (!(options
& EDITOR_NO_SCROLL
)) {
340 w
->vert_scrollbar
= CDrawVerticalScrollbar (catstrs (identifier
, ".vsc", 0), parent
,
341 x
+ width
+ EDIT_FRAME_W
+ WIDGET_SPACING
, y
, height
+ EDIT_FRAME_H
, 20, 0, 0);
342 CSetScrollbarCallback (w
->vert_scrollbar
->ident
, w
->ident
, link_scrollbar_to_editor
);
343 w
->vert_scrollbar
->scroll_bar_extra_render
= render_book_marks
;
348 static void render_book_marks (CWidget
* w
)
350 struct _book_mark
*p
;
356 strcpy (i
, CIdentOf (w
));
357 *(strstr (i
, ".vsc")) = '\0';
358 edit
= (CIdent (i
))->editor
;
359 if (!edit
->book_mark
)
361 l
= CHeightOf (w
) - 10 * CWidthOf (w
) / 3 - 10;
362 for (p
= edit
->book_mark
; p
->next
; p
= p
->next
);
363 for (; p
->prev
; p
= p
->prev
) {
364 int y
= (CWidthOf (w
) + 2 * CWidthOf (w
) / 3 + 4) + (int) ((double) l
* p
->line
/ edit
->total_lines
);
365 CSetColor (color_palette (p
->c
& 0xFF));
366 CLine (CWindowOf (w
), 5, y
, CWidthOf (w
) - 6, y
);
370 void update_scroll_bars (WEdit
* e
)
374 scroll
= e
->widget
->vert_scrollbar
;
376 i
= e
->total_lines
- e
->start_line
+ 1;
377 if (i
> e
->num_widget_lines
)
378 i
= e
->num_widget_lines
;
379 if (e
->total_lines
) {
380 x1
= (double) 65535.0 *e
->start_line
/ (e
->total_lines
+ 1);
381 x2
= (double) 65535.0 *i
/ (e
->total_lines
+ 1);
386 if (x1
!= scroll
->firstline
|| x2
!= scroll
->numlines
) {
387 scroll
->firstline
= x1
;
388 scroll
->numlines
= x2
;
389 EditExposeRedraw
= 1;
390 render_scrollbar (scroll
);
391 EditExposeRedraw
= 0;
394 scroll
= e
->widget
->hori_scrollbar
;
396 i
= e
->max_column
- (-e
->start_col
) + 1;
397 if (i
> e
->num_widget_columns
* FONT_MEAN_WIDTH
)
398 i
= e
->num_widget_columns
* FONT_MEAN_WIDTH
;
399 x1
= (double) 65535.0 *(-e
->start_col
) / (e
->max_column
+ 1);
400 x2
= (double) 65535.0 *i
/ (e
->max_column
+ 1);
401 if (x1
!= scroll
->firstline
|| x2
!= scroll
->numlines
) {
402 scroll
->firstline
= x1
;
403 scroll
->numlines
= x2
;
404 EditExposeRedraw
= 1;
405 render_scrollbar (scroll
);
406 EditExposeRedraw
= 0;
411 void edit_mouse_mark (WEdit
* edit
, XEvent
* event
, int double_click
)
413 edit_update_curs_row (edit
);
414 edit_update_curs_col (edit
);
415 if (event
->type
!= MotionNotify
) {
416 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
417 if (edit
->mark2
== -1)
418 edit_push_action (edit
, MARK_1
+ edit
->mark1
); /* mark1 must be following the cursor */
420 if (event
->type
== ButtonPress
) {
431 void link_scrollbar_to_editor (CWidget
* scrollbar
, CWidget
* editor
, XEvent
* xevent
, CEvent
* cwevent
, int whichscrbutton
)
438 if (!e
->widget
->vert_scrollbar
)
440 start_line
= e
->start_line
;
441 if ((xevent
->type
== ButtonRelease
|| xevent
->type
== MotionNotify
) && whichscrbutton
== 3) {
442 edit_move_display (e
, (double) scrollbar
->firstline
* e
->total_lines
/ 65535.0 + 1);
443 } else if (xevent
->type
== ButtonPress
&& (cwevent
->button
== Button1
|| cwevent
->button
== Button2
)) {
444 switch (whichscrbutton
) {
446 edit_move_display (e
, e
->start_line
- e
->num_widget_lines
+ 1);
449 edit_move_display (e
, e
->start_line
- 1);
452 edit_move_display (e
, e
->start_line
+ 1);
455 edit_move_display (e
, e
->start_line
+ e
->num_widget_lines
- 1);
460 scrollbar
->firstline
= (double) 65535.0 *e
->start_line
/ (e
->total_lines
+ 1);
462 scrollbar
->firstline
= 0;
463 i
= e
->total_lines
- e
->start_line
+ 1;
464 if (i
> e
->num_widget_lines
)
465 i
= e
->num_widget_lines
;
467 scrollbar
->numlines
= (double) 65535.0 *i
/ (e
->total_lines
+ 1);
469 scrollbar
->numlines
= 65535;
470 if (start_line
!= e
->start_line
) {
471 e
->force
|= REDRAW_PAGE
| REDRAW_LINE
;
472 set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
473 if (CCheckWindowEvent (xevent
->xany
.window
, ButtonReleaseMask
| ButtonMotionMask
, 0))
477 edit_render_keypress (e
);
482 void link_hscrollbar_to_editor (CWidget
* scrollbar
, CWidget
* editor
, XEvent
* xevent
, CEvent
* cwevent
, int whichscrbutton
)
489 if (!e
->widget
->hori_scrollbar
)
491 start_col
= (-e
->start_col
);
492 if ((xevent
->type
== ButtonRelease
|| xevent
->type
== MotionNotify
) && whichscrbutton
== 3) {
493 e
->start_col
= (double) scrollbar
->firstline
* e
->max_column
/ 65535.0 + 1;
494 e
->start_col
-= e
->start_col
% FONT_MEAN_WIDTH
;
495 if (e
->start_col
< 0)
497 e
->start_col
= (-e
->start_col
);
498 } else if (xevent
->type
== ButtonPress
&& (cwevent
->button
== Button1
|| cwevent
->button
== Button2
)) {
499 switch (whichscrbutton
) {
501 edit_scroll_left (e
, (e
->num_widget_columns
- 1) * FONT_MEAN_WIDTH
);
504 edit_scroll_left (e
, FONT_MEAN_WIDTH
);
507 edit_scroll_right (e
, FONT_MEAN_WIDTH
);
510 edit_scroll_right (e
, (e
->num_widget_columns
- 1) * FONT_MEAN_WIDTH
);
514 scrollbar
->firstline
= (double) 65535.0 *(-e
->start_col
) / (e
->max_column
+ 1);
515 i
= e
->max_column
- (-e
->start_col
) + 1;
516 if (i
> e
->num_widget_columns
* FONT_MEAN_WIDTH
)
517 i
= e
->num_widget_columns
* FONT_MEAN_WIDTH
;
518 scrollbar
->numlines
= (double) 65535.0 *i
/ (e
->max_column
+ 1);
519 if (start_col
!= (-e
->start_col
)) {
520 e
->force
|= REDRAW_PAGE
| REDRAW_LINE
;
521 set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
522 if (CCheckWindowEvent (xevent
->xany
.window
, ButtonReleaseMask
| ButtonMotionMask
, 0))
526 edit_render_keypress (e
);
532 This section comes from rxvt-2.21b1/src/screen.c by
533 Robert Nation <nation@rocket.sanders.lockheed.com> &
534 mods by mj olesen <olesen@me.QueensU.CA>
536 Changes made for cooledit
538 void selection_send (XSelectionRequestEvent
* rq
)
541 static Atom xa_targets
= None
;
542 if (xa_targets
== None
)
543 xa_targets
= XInternAtom (CDisplay
, "TARGETS", False
);
545 ev
.xselection
.type
= SelectionNotify
;
546 ev
.xselection
.property
= None
;
547 ev
.xselection
.display
= rq
->display
;
548 ev
.xselection
.requestor
= rq
->requestor
;
549 ev
.xselection
.selection
= rq
->selection
;
550 ev
.xselection
.target
= rq
->target
;
551 ev
.xselection
.time
= rq
->time
;
553 if (rq
->target
== xa_targets
) {
555 * On some systems, the Atom typedef is 64 bits wide.
556 * We need to have a typedef that is exactly 32 bits wide,
557 * because a format of 64 is not allowed by the X11 protocol.
559 * XXX: yes, but Xlib requires that you pass it 64 bits for 32bit
560 * quantities on 64 bit archs.
562 /* typedef CARD32 Atom32; */
566 target_list
[0] = xa_targets
;
567 target_list
[1] = XA_STRING
;
569 XChangeProperty (CDisplay
, rq
->requestor
, rq
->property
,
570 xa_targets
, 8 * sizeof (target_list
[0]), PropModeReplace
,
571 (unsigned char *) target_list
,
572 sizeof (target_list
) / sizeof (target_list
[0]));
573 ev
.xselection
.property
= rq
->property
;
574 } else if (rq
->target
== XA_STRING
) {
575 XChangeProperty (CDisplay
, rq
->requestor
, rq
->property
,
576 XA_STRING
, 8, PropModeReplace
,
577 selection
.text
, selection
.len
);
578 ev
.xselection
.property
= rq
->property
;
580 XSendEvent (CDisplay
, rq
->requestor
, False
, 0, &ev
);
583 /*{{{ paste selection */
586 * Respond to a notification that a primary selection has been sent
588 void paste_prop (void *data
, void (*insert
) (void *, int), Window win
, unsigned prop
, int delete)
591 unsigned long bytes_after
;
601 unsigned long nitems
;
603 if (XGetWindowProperty (CDisplay
, win
, prop
,
604 nread
/ 4, 65536, delete,
605 AnyPropertyType
, &actual_type
, &actual_fmt
,
606 &nitems
, &bytes_after
,
612 for (i
= 0; i
< nitems
; i
++)
613 (*insert
) (data
, s
[i
]);
615 } while (bytes_after
);
618 void selection_paste (WEdit
* edit
, Window win
, unsigned prop
, int delete)
622 paste_prop ((void *) edit
,
623 (void (*)(void *, int)) edit_insert
,
625 edit_cursor_move (edit
, c
- edit
->curs1
);
626 edit
->force
|= REDRAW_COMPLETELY
| REDRAW_LINE
;
631 void selection_clear (void)
637 void edit_update_screen (WEdit
* e
)
644 edit_scroll_screen_over_cursor (e
);
645 edit_update_curs_row (e
);
646 edit_update_curs_col (e
);
647 update_scroll_bars (e
);
650 if (e
->force
& REDRAW_COMPLETELY
)
651 e
->force
|= REDRAW_PAGE
;
653 /* pop all events for this window for internal handling */
654 if (e
->force
& (REDRAW_CHAR_ONLY
| REDRAW_COMPLETELY
)) {
655 edit_render_keypress (e
);
656 } else if (CCheckWindowEvent (e
->widget
->winid
, ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
, 0)
658 e
->force
|= REDRAW_PAGE
;
661 edit_render_keypress (e
);
665 extern int space_width
;
668 #define free_data if (data) {free(data);data=0;}
670 /* handles drag and drop */
671 void handle_client_message (CWidget
* w
, XEvent
* xevent
)
674 unsigned char *data
= 0;
678 int x
, y
, r
, deleted
= 0;
681 long start_mark
= 0, end_mark
= 0;
682 WEdit
*e
= w
->editor
;
684 /* see just below for a comment on what this is for: */
685 if (CIsDropAcknowledge (xevent
, &state
) != DndNotDnd
) {
686 if (!(state
& Button1Mask
) && just_dropped_something
) {
687 edit_push_action (e
, KEY_PRESS
+ e
->start_display
);
688 edit_block_delete_cmd (e
);
692 data_type
= CGetDrop (xevent
, &data
, &size
, &xs
, &ys
);
694 if (data_type
== DndNotDnd
|| xs
< 0 || ys
< 0 || xs
>= CWidthOf (w
) || ys
>= CHeightOf (w
)) {
698 edit_translate_xy (xs
, ys
, &x
, &y
);
699 click
= edit_get_click_pos (e
, x
, y
);
701 r
= eval_marks (e
, &start_mark
, &end_mark
);
702 /* musn't be able to drop into a block, otherwise a single click will copy a block: */
705 if (start_mark
> click
|| click
>= end_mark
)
707 if (column_highlighting
) {
708 if (!((x
>= e
->column1
&& x
< e
->column2
)
709 || (x
> e
->column2
&& x
<= e
->column1
)))
715 edit_push_action (e
, KEY_PRESS
+ e
->start_display
);
717 /* drops to the same window moving to the left: */
718 start_line
= e
->start_line
;
719 if (xevent
->xclient
.data
.l
[2] == xevent
->xclient
.window
&& !(xevent
->xclient
.data
.l
[1] & Button1Mask
))
720 if ((column_highlighting
&& x
< max (e
->column1
, e
->column2
)) || !column_highlighting
) {
721 edit_block_delete_cmd (e
);
724 edit_update_curs_row (e
);
725 edit_move_display (e
, start_line
);
726 click
= edit_get_click_pos (e
, x
, y
); /* click pos changes with edit_block_delete_cmd() */
727 edit_cursor_move (e
, click
- e
->curs1
);
728 if (data_type
== DndFile
) {
729 edit_insert_file (e
, (char *) data
);
730 } else if (data_type
!= DndFiles
) {
731 if (dnd_null_term_type (data_type
)) {
733 len
= strlen ((char *) data
);
734 size
= min (len
, size
);
736 if (column_highlighting
) {
737 edit_insert_column_of_text (e
, data
, size
, abs (e
->column2
- e
->column1
));
740 edit_insert_ahead (e
, data
[size
]);
744 edit_insert_ahead (e
, data
[size
] ? data
[size
] : '\n');
747 /* drops to the same window moving to the right: */
748 if (xevent
->xclient
.data
.l
[2] == xevent
->xclient
.window
&& !(xevent
->xclient
.data
.l
[1] & Button1Mask
))
749 if (column_highlighting
&& !deleted
)
750 edit_block_delete_cmd (e
);
752 /* The drop has now been successfully recieved. We can now send an acknowledge
753 event back to the window that send the data. When this window recieves
754 the acknowledge event, the app can decide whether or not to delete the data.
755 This allows text to be safely moved betweem text windows without the
756 risk of data being lost. In our case, drag with button1 is a copy
757 drag, while drag with any other button is a move drag (i.e. the sending
758 application must delete its selection after recieving an acknowledge
759 event). We must not, however, send an acknowledge signal if a filelist
760 (for example) was passed to us, since the sender might take this to
761 mean that all those files can be deleted! The two types we can acknowledge
763 if (xevent
->xclient
.data
.l
[2] != xevent
->xclient
.window
) /* drops to the same window */
764 if (data_type
== DndText
|| data_type
== DndRawData
)
765 CDropAcknowledge (xevent
);
766 e
->force
|= REDRAW_COMPLETELY
| REDRAW_LINE
;
771 int eh_editor (CWidget
* w
, XEvent
* xevent
, CEvent
* cwevent
)
773 WEdit
*e
= w
->editor
;
775 static int old_tab_spacing
= -1;
780 if (old_tab_spacing
!= option_tab_spacing
)
781 e
->force
|= REDRAW_COMPLETELY
+ REDRAW_LINE
;
782 old_tab_spacing
= option_tab_spacing
;
784 if (xevent
->type
== KeyPress
) {
785 if (xevent
->xkey
.keycode
== 0x31 && xevent
->xkey
.state
== 0xD) {
786 CSetColor (color_palette (18));
787 CRectangle (w
->winid
, 0, 0, w
->width
, w
->height
);
790 switch (xevent
->type
) {
791 case SelectionNotify
:
792 selection_paste (e
, xevent
->xselection
.requestor
, xevent
->xselection
.property
, True
);
795 case SelectionRequest
:
796 selection_send (&(xevent
->xselectionrequest
));
798 /* case SelectionClear: ---> This is handled by coolnext.c: CNextEvent() */
801 handle_client_message (w
, xevent
);
807 edit_render_tidbits (w
);
809 if (xevent
->xbutton
.state
& ControlMask
) {
810 if (!column_highlighting
)
811 edit_push_action (e
, COLUMN_OFF
);
812 column_highlighting
= 1;
814 if (column_highlighting
)
815 edit_push_action (e
, COLUMN_ON
);
816 column_highlighting
= 0;
819 if (!xevent
->xmotion
.state
&& xevent
->type
== MotionNotify
)
821 resolve_button (xevent
, cwevent
);
822 if ((cwevent
->button
== Button4
|| cwevent
->button
== Button5
)
823 && (xevent
->type
== ButtonRelease
)) {
824 /* ahaack: wheel mouse mapped as button 4 and 5 */
825 r
= edit_execute_key_command (e
, (cwevent
->button
== Button5
) ? CK_Page_Down
: CK_Page_Up
, -1);
828 edit_mouse_mark (e
, xevent
, cwevent
->double_click
);
831 edit_render_expose (e
, &(xevent
->xexpose
));
834 CSetCursorColor (e
->overwrite
? color_palette (24) : color_palette (19));
836 edit_render_tidbits (w
);
837 e
->force
|= REDRAW_CHAR_ONLY
| REDRAW_LINE
;
838 edit_render_keypress (e
);
843 if (column_highlighting
) {
844 column_highlighting
= 0;
845 e
->force
= REDRAW_COMPLETELY
| REDRAW_LINE
;
846 edit_mark_cmd (e
, 1);
851 cwevent
->ident
= w
->ident
;
852 if (!cwevent
->command
&& cwevent
->insert
< 0) { /* no translation */
853 if ((cwevent
->key
== XK_r
|| cwevent
->key
== XK_R
) && (cwevent
->state
& ControlMask
)) {
854 cwevent
->command
= e
->macro_i
< 0 ? CK_Begin_Record_Macro
: CK_End_Record_Macro
;
856 cwevent
->command
= CKeySymMod (xevent
);
857 if (cwevent
->command
> 0)
858 cwevent
->command
= CK_Macro (cwevent
->command
);
863 r
= edit_execute_key_command (e
, cwevent
->command
, cwevent
->insert
);
865 edit_update_screen (e
);
869 cwevent
->ident
= w
->ident
;
870 cwevent
->command
= xevent
->xkey
.keycode
;
871 r
= cwevent
->handled
= edit_execute_key_command (e
, xevent
->xkey
.keycode
, -1);
873 edit_update_screen (e
);
878 edit_update_screen (e
);
885 WButtonBar
*edit_bar
;
889 int column_highlighting
= 0;
891 static int edit_callback (Dlg_head
* h
, WEdit
* edit
, int msg
, int par
);
893 static int edit_mode_callback (struct Dlg_head
*h
, int id
, int msg
)
898 int edit_event (WEdit
* edit
, Gpm_Event
* event
, int *result
)
900 *result
= MOU_NORMAL
;
901 edit_update_curs_row (edit
);
902 edit_update_curs_col (edit
);
903 if (event
->type
& (GPM_DOWN
| GPM_DRAG
| GPM_UP
)) {
904 if (event
->y
> 1 && event
->x
> 0
905 && event
->x
<= edit
->num_widget_columns
906 && event
->y
<= edit
->num_widget_lines
+ 1) {
907 if (edit
->mark2
!= -1 && event
->type
& (GPM_UP
| GPM_DRAG
))
908 return 1; /* a lone up mustn't do anything */
909 if (event
->type
& (GPM_DOWN
| GPM_UP
))
910 edit_push_key_press (edit
);
911 edit_cursor_move (edit
, edit_bol (edit
, edit
->curs1
) - edit
->curs1
);
912 if (--event
->y
> (edit
->curs_row
+ 1))
913 edit_cursor_move (edit
,
914 edit_move_forward (edit
, edit
->curs1
, event
->y
- (edit
->curs_row
+ 1), 0)
916 if (event
->y
< (edit
->curs_row
+ 1))
917 edit_cursor_move (edit
,
918 +edit_move_backward (edit
, edit
->curs1
, (edit
->curs_row
+ 1) - event
->y
)
920 edit_cursor_move (edit
, (int) edit_move_forward3 (edit
, edit
->curs1
,
921 event
->x
- edit
->start_col
- 1, 0) - edit
->curs1
);
922 edit
->prev_col
= edit_get_col (edit
);
923 if (event
->type
& GPM_DOWN
) {
924 edit_mark_cmd (edit
, 1); /* reset */
927 if (!(event
->type
& GPM_DRAG
))
928 edit_mark_cmd (edit
, 0);
929 edit
->force
|= REDRAW_COMPLETELY
;
930 edit_update_curs_row (edit
);
931 edit_update_curs_col (edit
);
932 edit_update_screen (edit
);
941 int menubar_event (Gpm_Event
* event
, WMenu
* menubar
); /* menu.c */
943 int edit_mouse_event (Gpm_Event
* event
, void *x
)
946 if (edit_event ((WEdit
*) x
, event
, &result
))
949 return menubar_event (event
, edit_menubar
);
952 extern Menu EditMenuBar
[5];
954 int edit (const char *_file
, int line
)
956 static int made_directory
= 0;
958 int midnight_colors
[4];
961 if (option_backup_ext_int
!= -1) {
962 option_backup_ext
= malloc (sizeof(int) + 1);
963 option_backup_ext
[sizeof(int)] = '\0';
964 memcpy (option_backup_ext
, (char *) &option_backup_ext_int
, sizeof (int));
967 if (!made_directory
) {
968 mkdir (catstrs (home_dir
, EDIT_DIR
, 0), 0700);
979 if (!(wedit
= edit_init (NULL
, LINES
- 2, COLS
, _file
, text
, "", 0))) {
980 message (1, _(" Error "), get_error_msg (""));
985 /* Create a new dialog and add it widgets to it */
986 edit_dlg
= create_dlg (0, 0, LINES
, COLS
, midnight_colors
,
987 edit_mode_callback
, "[Internal File Editor]",
991 edit_dlg
->raw
= 1; /*so that tab = '\t' key works */
993 init_widget (&(wedit
->widget
), 0, 0, LINES
- 1, COLS
,
994 (callback_fn
) edit_callback
,
995 (destroy_fn
) edit_clean
,
996 (mouse_h
) edit_mouse_event
, 0);
998 widget_want_cursor (wedit
->widget
, 1);
1000 edit_bar
= buttonbar_new (1);
1003 switch (edit_key_emulation
) {
1004 case EDIT_KEY_EMULATION_NORMAL
:
1005 edit_init_menu_normal (); /* editmenu.c */
1007 case EDIT_KEY_EMULATION_EMACS
:
1008 edit_init_menu_emacs (); /* editmenu.c */
1011 edit_menubar
= menubar_new (0, 0, COLS
, EditMenuBar
, N_menus
);
1013 add_widget (edit_dlg
, wedit
);
1016 add_widget (edit_dlg
, edit_menubar
);
1018 add_widget (edit_dlg
, edit_bar
);
1019 edit_move_display (wedit
, line
- 1);
1020 edit_move_to_line (wedit
, line
- 1);
1025 edit_done_menu (); /* editmenu.c */
1027 destroy_dlg (edit_dlg
);
1032 static void edit_my_define (Dlg_head
* h
, int idx
, char *text
,
1033 void (*fn
) (WEdit
*), WEdit
* edit
)
1035 define_label_data (h
, (Widget
*) edit
, idx
, text
, (buttonbarfn
) fn
, edit
);
1039 void cmd_F1 (WEdit
* edit
)
1041 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (1));
1044 void cmd_F2 (WEdit
* edit
)
1046 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (2));
1049 void cmd_F3 (WEdit
* edit
)
1051 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (3));
1054 void cmd_F4 (WEdit
* edit
)
1056 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (4));
1059 void cmd_F5 (WEdit
* edit
)
1061 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (5));
1064 void cmd_F6 (WEdit
* edit
)
1066 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (6));
1069 void cmd_F7 (WEdit
* edit
)
1071 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (7));
1074 void cmd_F8 (WEdit
* edit
)
1076 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (8));
1079 void cmd_F9 (WEdit
* edit
)
1081 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (9));
1084 void cmd_F10 (WEdit
* edit
)
1086 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (10));
1089 void edit_labels (WEdit
* edit
)
1091 Dlg_head
*h
= edit
->widget
.parent
;
1093 edit_my_define (h
, 1, _("Help"), cmd_F1
, edit
);
1094 edit_my_define (h
, 2, _("Save"), cmd_F2
, edit
);
1095 edit_my_define (h
, 3, _("Mark"), cmd_F3
, edit
);
1096 edit_my_define (h
, 4, _("Replac"), cmd_F4
, edit
);
1097 edit_my_define (h
, 5, _("Copy"), cmd_F5
, edit
);
1098 edit_my_define (h
, 6, _("Move"), cmd_F6
, edit
);
1099 edit_my_define (h
, 7, _("Search"), cmd_F7
, edit
);
1100 edit_my_define (h
, 8, _("Delete"), cmd_F8
, edit
);
1101 if (!edit
->have_frame
)
1102 edit_my_define (h
, 9, _("PullDn"), edit_menu_cmd
, edit
);
1103 edit_my_define (h
, 10, _("Quit"), cmd_F10
, edit
);
1105 redraw_labels (h
, (Widget
*) edit
);
1109 long get_key_state ()
1111 return (long) get_modifier ();
1114 void edit_adjust_size (Dlg_head
* h
)
1117 WButtonBar
*edit_bar
;
1119 edit
= (WEdit
*) find_widget_type (h
, (callback_fn
) edit_callback
);
1120 edit_bar
= (WButtonBar
*) edit
->widget
.parent
->current
->next
->widget
;
1121 widget_set_size (&edit
->widget
, 0, 0, LINES
- 1, COLS
);
1122 widget_set_size (&edit_bar
->widget
, LINES
- 1, 0, 1, COLS
);
1123 widget_set_size (&edit_menubar
->widget
, 0, 0, 1, COLS
);
1125 #ifdef RESIZABLE_MENUBAR
1126 menubar_arrange(edit_menubar
);
1130 void edit_update_screen (WEdit
* e
)
1132 edit_scroll_screen_over_cursor (e
);
1134 edit_update_curs_col (e
);
1137 /* pop all events for this window for internal handling */
1140 e
->force
|= REDRAW_PAGE
;
1143 if (e
->force
& REDRAW_COMPLETELY
)
1144 e
->force
|= REDRAW_PAGE
;
1145 edit_render_keypress (e
);
1148 static int edit_callback (Dlg_head
* h
, WEdit
* e
, int msg
, int par
)
1152 e
->force
|= REDRAW_COMPLETELY
;
1156 e
->force
|= REDRAW_COMPLETELY
;
1157 e
->num_widget_lines
= LINES
- 2;
1158 e
->num_widget_columns
= COLS
;
1160 edit_update_screen (e
);
1164 if (edit_drop_hotkey_menu (e
, par
)) /* first check alt-f, alt-e, alt-s, etc for drop menus */
1166 if (!edit_translate_key (e
, 0, par
, get_key_state (), &cmd
, &ch
))
1168 edit_execute_key_command (e
, cmd
, ch
);
1169 edit_update_screen (e
);
1172 case WIDGET_COMMAND
:
1173 edit_execute_key_command (e
, par
, -1);
1174 edit_update_screen (e
);
1177 widget_move (&e
->widget
, e
->curs_row
+ EDIT_TEXT_VERTICAL_OFFSET
, e
->curs_col
+ e
->start_col
);
1180 return default_proc (h
, msg
, par
);