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)
41 extern int EditExposeRedraw
;
44 void edit_destroy_callback (CWidget
* w
)
47 edit_clean (w
->editor
);
53 CError ("Trying to destroy non-existing editor widget.\n");
56 void link_hscrollbar_to_editor (CWidget
* scrollbar
, CWidget
* editor
, XEvent
* xevent
, CEvent
* cwevent
, int whichscrbutton
);
58 /* returns the position in the edit buffer of a window click */
59 long edit_get_click_pos (WEdit
* edit
, int x
, int y
)
62 /* (1) goto to left margin */
63 click
= edit_bol (edit
, edit
->curs1
);
65 /* (1) move up or down */
66 if (y
> (edit
->curs_row
+ 1))
67 click
= edit_move_forward (edit
, click
, y
- (edit
->curs_row
+ 1), 0);
68 if (y
< (edit
->curs_row
+ 1))
69 click
= edit_move_backward (edit
, click
, (edit
->curs_row
+ 1) - y
);
71 /* (3) move right to x pos */
72 click
= edit_move_forward3 (edit
, click
, x
- edit
->start_col
- 1, 0);
76 void edit_translate_xy (int xs
, int ys
, int *x
, int *y
)
78 *x
= xs
- EDIT_TEXT_HORIZONTAL_OFFSET
;
79 *y
= (ys
- EDIT_TEXT_VERTICAL_OFFSET
- option_text_line_spacing
/ 2 - 1) / FONT_PIX_PER_LINE
+ 1;
82 extern int just_dropped_something
;
84 void mouse_redraw (WEdit
* edit
, long click
)
86 edit
->force
|= REDRAW_PAGE
| REDRAW_LINE
;
87 edit_update_curs_row (edit
);
88 edit_update_curs_col (edit
);
89 edit
->prev_col
= edit_get_col (edit
);
90 edit_update_screen (edit
);
91 edit
->search_start
= click
;
94 static void xy (int x
, int y
, int *x_return
, int *y_return
)
96 edit_translate_xy (x
, y
, x_return
, y_return
);
99 static long cp (WEdit
* edit
, int x
, int y
)
101 return edit_get_click_pos (edit
, x
, y
);
104 /* return 1 if not marked */
105 static int marks (WEdit
* edit
, long *start
, long *end
)
107 return eval_marks (edit
, start
, end
);
110 int column_highlighting
= 0;
112 static int erange (WEdit
* edit
, long start
, long end
, int click
)
114 if (column_highlighting
) {
116 x
= edit_move_forward3 (edit
, edit_bol (edit
, click
), 0, click
);
117 if ((x
>= edit
->column1
&& x
< edit
->column2
)
118 || (x
> edit
->column2
&& x
<= edit
->column1
))
119 return (start
<= click
&& click
< end
);
123 return (start
<= click
&& click
< end
);
126 static void fin_mark (WEdit
* edit
)
129 edit_mark_cmd (edit
, 0);
132 static void move_mark (WEdit
* edit
)
134 edit_mark_cmd (edit
, 1);
135 edit_mark_cmd (edit
, 0);
138 static void release_mark (WEdit
* edit
, XEvent
* event
)
141 edit_mark_cmd (edit
, 0);
143 edit_mark_cmd (edit
, 1);
144 if (edit
->mark1
!= edit
->mark2
&& event
) {
145 edit_get_selection (edit
);
146 XSetSelectionOwner (CDisplay
, XA_PRIMARY
, CWindowOf (edit
->widget
), event
->xbutton
.time
);
150 edit
->widget
->editable
.has_selection
= TRUE
;
155 static char *get_block (WEdit
* edit
, long start_mark
, long end_mark
, int *type
, int *l
)
158 t
= (char *) edit_get_block (edit
, start_mark
, end_mark
, l
);
160 *type
= DndRawData
; /* if there are nulls in the data, send as raw */
162 *type
= DndText
; /* else send as text */
166 static void move (WEdit
* edit
, long click
, int y
)
168 edit_cursor_move (edit
, click
- edit
->curs1
);
171 static void dclick (WEdit
* edit
, XEvent
* event
)
173 edit_mark_cmd (edit
, 1);
174 edit_right_word_move (edit
, 1);
175 edit_mark_cmd (edit
, 0);
176 edit_left_word_move (edit
, 1);
177 release_mark (edit
, event
);
180 static void redraw (WEdit
* edit
, long click
)
182 mouse_redraw (edit
, click
);
185 void edit_insert_column_of_text (WEdit
* edit
, unsigned char *data
, int size
, int width
);
187 /* strips out the first i chars and returns a null terminated string, result must be free'd */
188 char *filename_from_url (char *data
, int size
, int i
)
192 for (p
= data
+ i
; (unsigned long) p
- (unsigned long) data
< size
&& *p
&& *p
!= '\n'; p
++);
193 l
= (unsigned long) p
- (unsigned long) data
- i
;
195 memcpy (f
, data
+ i
, l
);
200 static int insert_drop (WEdit
* e
, Window from
, unsigned char *data
, int size
, int xs
, int ys
, Atom type
, Atom action
)
202 long start_mark
= 0, end_mark
= 0;
205 edit_translate_xy (xs
, ys
, &x
, &y
);
206 /* musn't be able to drop into a block, otherwise a single click will copy a block: */
207 if (eval_marks (e
, &start_mark
, &end_mark
))
209 if (start_mark
> e
->curs1
|| e
->curs1
>= end_mark
)
211 if (column_highlighting
) {
212 if (!((x
>= e
->column1
&& x
< e
->column2
)
213 || (x
> e
->column2
&& x
<= e
->column1
)))
218 if (from
== e
->widget
->winid
&& action
== CDndClass
->XdndActionMove
) {
219 edit_block_move_cmd (e
);
220 edit_mark_cmd (e
, 1);
222 } else if (from
== e
->widget
->winid
) {
223 edit_block_copy_cmd (e
);
225 } else { /* data from another widget, or from another application */
226 edit_push_action (e
, KEY_PRESS
+ e
->start_display
);
227 if (type
== XInternAtom (CDisplay
, "url/url", False
)) {
228 if (!strncmp ((char *) data
, "file:/", 6)) {
230 edit_insert_file (e
, f
= filename_from_url ((char *) data
, size
, strlen ("file:")));
234 edit_insert_ahead (e
, data
[size
]);
237 if (column_highlighting
) {
238 edit_insert_column_of_text (e
, data
, size
, abs (e
->column2
- e
->column1
));
241 edit_insert_ahead (e
, data
[size
]);
245 CExpose (e
->widget
->ident
);
249 static char *mime_majors
[2] =
252 struct mouse_funcs edit_mouse_funcs
=
255 (void (*)(int, int, int *, int *)) xy
,
256 (long (*)(void *, int, int)) cp
,
257 (int (*)(void *, long *, long *)) marks
,
258 (int (*)(void *, long, long, long)) erange
,
259 (void (*)(void *)) fin_mark
,
260 (void (*)(void *)) move_mark
,
261 (void (*)(void *, XEvent
*)) release_mark
,
262 (char *(*)(void *, long, long, int *, int *)) get_block
,
263 (void (*)(void *, long, int)) move
,
265 (void (*)(void *, XEvent
*)) dclick
,
266 (void (*)(void *, long)) redraw
,
267 (int (*)(void *, Window
, unsigned char *, int, int, int, Atom
, Atom
)) insert_drop
,
268 (void (*)(void *)) edit_block_delete
,
273 static void render_book_marks (CWidget
* w
);
274 extern int option_editor_bg_normal
;
275 void edit_tri_cursor (Window win
);
277 /* starting_directory is for the filebrowser */
278 CWidget
*CDrawEditor (const char *identifier
, Window parent
, int x
, int y
,
279 int width
, int height
, const char *text
, const char *filename
,
280 const char *starting_directory
, unsigned int options
, unsigned long text_size
)
282 static int made_directory
= 0;
283 int extra_space_for_hscroll
= 0;
287 CPushFont ("editor", 0);
290 if (options
& EDITOR_HORIZ_SCROLL
)
291 extra_space_for_hscroll
= 21;
293 if (options
& EDITOR_HORIZ_SCROLL
)
294 extra_space_for_hscroll
= 8;
296 wedit
= w
= CSetupWidget (identifier
, parent
, x
, y
,
297 width
+ EDIT_FRAME_W
, height
+ EDIT_FRAME_H
, C_EDITOR_WIDGET
,
298 ExposureMask
| ButtonPressMask
| ButtonReleaseMask
| \
299 KeyPressMask
| KeyReleaseMask
| ButtonMotionMask
| \
300 PropertyChangeMask
| StructureNotifyMask
| \
301 EnterWindowMask
| LeaveWindowMask
, color_palette (option_editor_bg_normal
), 1);
303 xdnd_set_dnd_aware (CDndClass
, w
->winid
, 0);
304 xdnd_set_type_list (CDndClass
, w
->winid
, xdnd_typelist_send
[DndText
]);
306 edit_tri_cursor (w
->winid
);
307 w
->options
= options
| WIDGET_TAKES_SELECTION
;
309 w
->destroy
= edit_destroy_callback
;
311 w
->label
= (char *) strdup (filename
);
313 w
->label
= (char *) strdup ("");
315 if (!made_directory
) {
316 mkdir (catstrs (home_dir
, EDIT_DIR
, 0), 0700);
319 e
= w
->editor
= CMalloc (sizeof (WEdit
));
320 w
->funcs
= mouse_funcs_new (w
->editor
, &edit_mouse_funcs
);
323 /* Not essential to translate */
324 CError (_ ("Error initialising editor.\n"));
328 w
->editor
->widget
= w
;
329 w
->editor
= edit_init (e
, height
/ FONT_PIX_PER_LINE
, width
/ FONT_MEAN_WIDTH
, filename
, text
, starting_directory
, text_size
);
330 w
->funcs
->data
= (void *) w
->editor
;
333 CDestroyWidget (w
->ident
);
340 if (!(options
& EDITOR_NO_SCROLL
)) {
341 w
->vert_scrollbar
= CDrawVerticalScrollbar (catstrs (identifier
, ".vsc", 0), parent
,
342 x
+ width
+ EDIT_FRAME_W
+ WIDGET_SPACING
, y
, height
+ EDIT_FRAME_H
,
349 CSetScrollbarCallback (w
->vert_scrollbar
->ident
, w
->ident
, link_scrollbar_to_editor
);
350 w
->vert_scrollbar
->scroll_bar_extra_render
= render_book_marks
;
352 set_hint_pos (x
+ width
+ EDIT_FRAME_W
+ WIDGET_SPACING
, y
+ height
+ EDIT_FRAME_H
+ WIDGET_SPACING
+ extra_space_for_hscroll
);
353 if (extra_space_for_hscroll
) {
354 w
->hori_scrollbar
= CDrawHorizontalScrollbar (catstrs (identifier
, ".hsc", 0), parent
,
355 x
, y
+ height
+ EDIT_FRAME_H
, width
+ EDIT_FRAME_W
,
362 CSetScrollbarCallback (w
->hori_scrollbar
->ident
, w
->ident
, link_hscrollbar_to_editor
);
365 if (!(options
& EDITOR_NO_TEXT
)) {
366 CPushFont ("widget", 0);
368 CDrawStatus (catstrs (identifier
, ".text", 0), parent
, x
, y
+ WIDGET_SPACING
+ NEXT_SPACING
, width
+ EDIT_FRAME_W
, e
->filename
);
370 CDrawStatus (catstrs (identifier
, ".text", 0), parent
, x
, y
, width
+ EDIT_FRAME_W
, e
->filename
);
378 static void render_book_marks (CWidget
* w
)
380 struct _book_mark
*p
;
386 strcpy (i
, CIdentOf (w
));
387 *(strstr (i
, ".vsc")) = '\0';
388 edit
= (CIdent (i
))->editor
;
389 if (!edit
->book_mark
)
391 l
= CHeightOf (w
) - 10 * CWidthOf (w
) / 3 - 10;
392 for (p
= edit
->book_mark
; p
->next
; p
= p
->next
);
393 for (; p
->prev
; p
= p
->prev
) {
394 int y
= (CWidthOf (w
) + 2 * CWidthOf (w
) / 3 + 4) + (int) ((double) l
* p
->line
/ edit
->total_lines
);
395 CSetColor (color_palette (((p
->c
& 0xFF00) >> 8) ? ((p
->c
& 0xFF00) >> 8) : (p
->c
& 0xFF)));
396 CLine (CWindowOf (w
), 5, y
, CWidthOf (w
) - 6, y
);
400 void update_scroll_bars (WEdit
* e
)
404 CPushFont ("editor", 0);
405 scroll
= e
->widget
->vert_scrollbar
;
407 i
= e
->total_lines
- e
->start_line
+ 1;
408 if (i
> e
->num_widget_lines
)
409 i
= e
->num_widget_lines
;
410 if (e
->total_lines
) {
411 x1
= (double) 65535.0 *e
->start_line
/ (e
->total_lines
+ 1);
412 x2
= (double) 65535.0 *i
/ (e
->total_lines
+ 1);
417 if (x1
!= scroll
->firstline
|| x2
!= scroll
->numlines
) {
418 scroll
->firstline
= x1
;
419 scroll
->numlines
= x2
;
420 EditExposeRedraw
= 1;
421 render_scrollbar (scroll
);
422 EditExposeRedraw
= 0;
425 scroll
= e
->widget
->hori_scrollbar
;
427 i
= e
->max_column
- (-e
->start_col
) + 1;
428 if (i
> e
->num_widget_columns
* FONT_MEAN_WIDTH
)
429 i
= e
->num_widget_columns
* FONT_MEAN_WIDTH
;
430 x1
= (double) 65535.0 *(-e
->start_col
) / (e
->max_column
+ 1);
431 x2
= (double) 65535.0 *i
/ (e
->max_column
+ 1);
432 if (x1
!= scroll
->firstline
|| x2
!= scroll
->numlines
) {
433 scroll
->firstline
= x1
;
434 scroll
->numlines
= x2
;
435 EditExposeRedraw
= 1;
436 render_scrollbar (scroll
);
437 EditExposeRedraw
= 0;
443 void edit_mouse_mark (WEdit
* edit
, XEvent
* event
, int double_click
)
445 CPushFont ("editor", 0);
446 edit_update_curs_row (edit
);
447 edit_update_curs_col (edit
);
448 if (event
->type
!= MotionNotify
) {
449 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
450 if (edit
->mark2
== -1)
451 edit_push_action (edit
, MARK_1
+ edit
->mark1
); /* mark1 must be following the cursor */
453 if (event
->type
== ButtonPress
) {
465 void link_scrollbar_to_editor (CWidget
* scrollbar
, CWidget
* editor
, XEvent
* xevent
, CEvent
* cwevent
, int whichscrbutton
)
472 if (!e
->widget
->vert_scrollbar
)
474 CPushFont ("editor", 0);
475 start_line
= e
->start_line
;
476 if ((xevent
->type
== ButtonRelease
|| xevent
->type
== MotionNotify
) && whichscrbutton
== 3) {
477 edit_move_display (e
, (double) scrollbar
->firstline
* e
->total_lines
/ 65535.0 + 1);
478 } else if (xevent
->type
== ButtonPress
&& (cwevent
->button
== Button1
|| cwevent
->button
== Button2
)) {
479 switch (whichscrbutton
) {
481 edit_move_display (e
, e
->start_line
- e
->num_widget_lines
+ 1);
484 edit_move_display (e
, e
->start_line
- 1);
487 edit_move_display (e
, e
->start_line
+ 1);
490 edit_move_display (e
, e
->start_line
+ e
->num_widget_lines
- 1);
495 scrollbar
->firstline
= (double) 65535.0 *e
->start_line
/ (e
->total_lines
+ 1);
497 scrollbar
->firstline
= 0;
498 i
= e
->total_lines
- e
->start_line
+ 1;
499 if (i
> e
->num_widget_lines
)
500 i
= e
->num_widget_lines
;
502 scrollbar
->numlines
= (double) 65535.0 *i
/ (e
->total_lines
+ 1);
504 scrollbar
->numlines
= 65535;
505 if (start_line
!= e
->start_line
) {
506 e
->force
|= REDRAW_PAGE
| REDRAW_LINE
;
507 set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
508 if (CCheckWindowEvent (xevent
->xany
.window
, ButtonReleaseMask
| ButtonMotionMask
, 0)) {
514 edit_render_keypress (e
);
520 void link_hscrollbar_to_editor (CWidget
* scrollbar
, CWidget
* editor
, XEvent
* xevent
, CEvent
* cwevent
, int whichscrbutton
)
527 if (!e
->widget
->hori_scrollbar
)
529 CPushFont ("editor", 0);
530 start_col
= (-e
->start_col
);
531 if ((xevent
->type
== ButtonRelease
|| xevent
->type
== MotionNotify
) && whichscrbutton
== 3) {
532 e
->start_col
= (double) scrollbar
->firstline
* e
->max_column
/ 65535.0 + 1;
533 e
->start_col
-= e
->start_col
% FONT_MEAN_WIDTH
;
534 if (e
->start_col
< 0)
536 e
->start_col
= (-e
->start_col
);
537 } else if (xevent
->type
== ButtonPress
&& (cwevent
->button
== Button1
|| cwevent
->button
== Button2
)) {
538 switch (whichscrbutton
) {
540 edit_scroll_left (e
, (e
->num_widget_columns
- 1) * FONT_MEAN_WIDTH
);
543 edit_scroll_left (e
, FONT_MEAN_WIDTH
);
546 edit_scroll_right (e
, FONT_MEAN_WIDTH
);
549 edit_scroll_right (e
, (e
->num_widget_columns
- 1) * FONT_MEAN_WIDTH
);
553 scrollbar
->firstline
= (double) 65535.0 *(-e
->start_col
) / (e
->max_column
+ 1);
554 i
= e
->max_column
- (-e
->start_col
) + 1;
555 if (i
> e
->num_widget_columns
* FONT_MEAN_WIDTH
)
556 i
= e
->num_widget_columns
* FONT_MEAN_WIDTH
;
557 scrollbar
->numlines
= (double) 65535.0 *i
/ (e
->max_column
+ 1);
558 if (start_col
!= (-e
->start_col
)) {
559 e
->force
|= REDRAW_PAGE
| REDRAW_LINE
;
560 set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
561 if (CCheckWindowEvent (xevent
->xany
.window
, ButtonReleaseMask
| ButtonMotionMask
, 0)) {
567 edit_render_keypress (e
);
574 This section comes from rxvt-2.21b1/src/screen.c by
575 Robert Nation <nation@rocket.sanders.lockheed.com> &
576 mods by mj olesen <olesen@me.QueensU.CA>
578 Changes made for cooledit
580 void selection_send (XSelectionRequestEvent
* rq
)
583 static Atom xa_targets
= None
;
584 if (xa_targets
== None
)
585 xa_targets
= XInternAtom (CDisplay
, "TARGETS", False
);
587 ev
.xselection
.type
= SelectionNotify
;
588 ev
.xselection
.property
= None
;
589 ev
.xselection
.display
= rq
->display
;
590 ev
.xselection
.requestor
= rq
->requestor
;
591 ev
.xselection
.selection
= rq
->selection
;
592 ev
.xselection
.target
= rq
->target
;
593 ev
.xselection
.time
= rq
->time
;
595 if (rq
->target
== xa_targets
) {
597 * On some systems, the Atom typedef is 64 bits wide.
598 * We need to have a typedef that is exactly 32 bits wide,
599 * because a format of 64 is not allowed by the X11 protocol.
601 * XXX: yes, but Xlib requires that you pass it 64 bits for 32bit
602 * quantities on 64 bit archs.
604 /* typedef CARD32 Atom32; */
608 target_list
[0] = xa_targets
;
609 target_list
[1] = XA_STRING
;
611 XChangeProperty (CDisplay
, rq
->requestor
, rq
->property
,
612 xa_targets
, 8 * sizeof (target_list
[0]), PropModeReplace
,
613 (unsigned char *) target_list
,
614 sizeof (target_list
) / sizeof (target_list
[0]));
615 ev
.xselection
.property
= rq
->property
;
616 } else if (rq
->target
== XA_STRING
) {
617 XChangeProperty (CDisplay
, rq
->requestor
, rq
->property
,
618 XA_STRING
, 8, PropModeReplace
,
619 selection
.text
, selection
.len
);
620 ev
.xselection
.property
= rq
->property
;
622 XSendEvent (CDisplay
, rq
->requestor
, False
, 0, &ev
);
625 /*{{{ paste selection */
628 * Respond to a notification that a primary selection has been sent
630 void paste_prop (void *data
, void (*insert
) (void *, int), Window win
, unsigned prop
, int delete)
633 unsigned long bytes_after
;
643 unsigned long nitems
;
645 if (XGetWindowProperty (CDisplay
, win
, prop
,
646 nread
/ 4, 65536, delete,
647 AnyPropertyType
, &actual_type
, &actual_fmt
,
648 &nitems
, &bytes_after
,
654 for (i
= 0; i
< nitems
; i
++)
655 (*insert
) (data
, s
[i
]);
657 } while (bytes_after
);
660 void selection_paste (WEdit
* edit
, Window win
, unsigned prop
, int delete)
664 paste_prop ((void *) edit
,
665 (void (*)(void *, int)) edit_insert
,
667 edit_cursor_move (edit
, c
- edit
->curs1
);
668 edit
->force
|= REDRAW_COMPLETELY
| REDRAW_LINE
;
673 void selection_clear (void)
679 void edit_update_screen (WEdit
* e
)
686 CPushFont ("editor", 0);
687 edit_scroll_screen_over_cursor (e
);
688 edit_update_curs_row (e
);
689 edit_update_curs_col (e
);
690 update_scroll_bars (e
);
693 if (e
->force
& REDRAW_COMPLETELY
)
694 e
->force
|= REDRAW_PAGE
;
696 /* pop all events for this window for internal handling */
697 if (e
->force
& (REDRAW_CHAR_ONLY
| REDRAW_COMPLETELY
)) {
698 edit_render_keypress (e
);
699 } else if (CCheckWindowEvent (e
->widget
->winid
, ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
, 0)
701 e
->force
|= REDRAW_PAGE
;
705 edit_render_keypress (e
);
710 extern int space_width
;
713 #define free_data if (data) {free(data);data=0;}
715 /* handles drag and drop */
716 void handle_client_message (CWidget
* w
, XEvent
* xevent
)
719 unsigned char *data
= 0;
723 int x
, y
, r
, deleted
= 0;
726 long start_mark
= 0, end_mark
= 0;
727 WEdit
*e
= w
->editor
;
729 /* see just below for a comment on what this is for: */
730 if (CIsDropAcknowledge (xevent
, &state
) != DndNotDnd
) {
731 if (!(state
& Button1Mask
) && just_dropped_something
) {
732 edit_push_action (e
, KEY_PRESS
+ e
->start_display
);
733 edit_block_delete_cmd (e
);
737 data_type
= CGetDrop (xevent
, &data
, &size
, &xs
, &ys
);
739 if (data_type
== DndNotDnd
|| xs
< 0 || ys
< 0 || xs
>= CWidthOf (w
) || ys
>= CHeightOf (w
)) {
743 edit_translate_xy (xs
, ys
, &x
, &y
);
744 click
= edit_get_click_pos (e
, x
, y
);
746 r
= eval_marks (e
, &start_mark
, &end_mark
);
747 /* musn't be able to drop into a block, otherwise a single click will copy a block: */
750 if (start_mark
> click
|| click
>= end_mark
)
752 if (column_highlighting
) {
753 if (!((x
>= e
->column1
&& x
< e
->column2
)
754 || (x
> e
->column2
&& x
<= e
->column1
)))
760 edit_push_action (e
, KEY_PRESS
+ e
->start_display
);
762 /* drops to the same window moving to the left: */
763 start_line
= e
->start_line
;
764 if (xevent
->xclient
.data
.l
[2] == xevent
->xclient
.window
&& !(xevent
->xclient
.data
.l
[1] & Button1Mask
))
765 if ((column_highlighting
&& x
< max (e
->column1
, e
->column2
)) || !column_highlighting
) {
766 edit_block_delete_cmd (e
);
769 edit_update_curs_row (e
);
770 edit_move_display (e
, start_line
);
771 click
= edit_get_click_pos (e
, x
, y
); /* click pos changes with edit_block_delete_cmd() */
772 edit_cursor_move (e
, click
- e
->curs1
);
773 if (data_type
== DndFile
) {
774 edit_insert_file (e
, (char *) data
);
775 } else if (data_type
!= DndFiles
) {
776 if (dnd_null_term_type (data_type
)) {
778 len
= strlen ((char *) data
);
779 size
= min (len
, size
);
781 if (column_highlighting
) {
782 edit_insert_column_of_text (e
, data
, size
, abs (e
->column2
- e
->column1
));
785 edit_insert_ahead (e
, data
[size
]);
789 edit_insert_ahead (e
, data
[size
] ? data
[size
] : '\n');
792 /* drops to the same window moving to the right: */
793 if (xevent
->xclient
.data
.l
[2] == xevent
->xclient
.window
&& !(xevent
->xclient
.data
.l
[1] & Button1Mask
))
794 if (column_highlighting
&& !deleted
)
795 edit_block_delete_cmd (e
);
797 /* The drop has now been successfully recieved. We can now send an acknowledge
798 event back to the window that send the data. When this window recieves
799 the acknowledge event, the app can decide whether or not to delete the data.
800 This allows text to be safely moved betweem text windows without the
801 risk of data being lost. In our case, drag with button1 is a copy
802 drag, while drag with any other button is a move drag (i.e. the sending
803 application must delete its selection after recieving an acknowledge
804 event). We must not, however, send an acknowledge signal if a filelist
805 (for example) was passed to us, since the sender might take this to
806 mean that all those files can be deleted! The two types we can acknowledge
808 if (xevent
->xclient
.data
.l
[2] != xevent
->xclient
.window
) /* drops to the same window */
809 if (data_type
== DndText
|| data_type
== DndRawData
)
810 CDropAcknowledge (xevent
);
811 e
->force
|= REDRAW_COMPLETELY
| REDRAW_LINE
;
816 int eh_editor (CWidget
* w
, XEvent
* xevent
, CEvent
* cwevent
)
818 WEdit
*e
= w
->editor
;
820 static int old_tab_spacing
= -1;
825 if (old_tab_spacing
!= option_tab_spacing
)
826 e
->force
|= REDRAW_COMPLETELY
+ REDRAW_LINE
;
827 old_tab_spacing
= option_tab_spacing
;
829 if (xevent
->type
== KeyPress
) {
830 if (xevent
->xkey
.keycode
== 0x31 && xevent
->xkey
.state
== 0xD) {
831 CSetColor (color_palette (18));
832 CRectangle (w
->winid
, 0, 0, w
->width
, w
->height
);
835 switch (xevent
->type
) {
836 case SelectionNotify
:
837 selection_paste (e
, xevent
->xselection
.requestor
, xevent
->xselection
.property
, True
);
840 case SelectionRequest
:
841 selection_send (&(xevent
->xselectionrequest
));
843 /* case SelectionClear: ---> This is handled by coolnext.c: CNextEvent() */
846 handle_client_message (w
, xevent
);
852 edit_render_tidbits (w
);
854 if (xevent
->xbutton
.state
& ControlMask
) {
855 if (!column_highlighting
)
856 edit_push_action (e
, COLUMN_OFF
);
857 column_highlighting
= 1;
859 if (column_highlighting
)
860 edit_push_action (e
, COLUMN_ON
);
861 column_highlighting
= 0;
864 if (!xevent
->xmotion
.state
&& xevent
->type
== MotionNotify
)
866 resolve_button (xevent
, cwevent
);
867 if ((cwevent
->button
== Button4
|| cwevent
->button
== Button5
)
868 && (xevent
->type
== ButtonRelease
)) {
869 /* ahaack: wheel mouse mapped as button 4 and 5 */
870 r
= edit_execute_key_command (e
, (cwevent
->button
== Button5
) ? CK_Page_Down
: CK_Page_Up
, -1);
873 edit_mouse_mark (e
, xevent
, cwevent
->double_click
);
876 edit_render_expose (e
, &(xevent
->xexpose
));
879 CSetCursorColor (e
->overwrite
? color_palette (24) : color_palette (19));
881 edit_render_tidbits (w
);
882 e
->force
|= REDRAW_CHAR_ONLY
| REDRAW_LINE
;
883 edit_render_keypress (e
);
888 if (column_highlighting
) {
889 column_highlighting
= 0;
890 e
->force
= REDRAW_COMPLETELY
| REDRAW_LINE
;
891 edit_mark_cmd (e
, 1);
896 cwevent
->ident
= w
->ident
;
897 if (!cwevent
->command
&& cwevent
->insert
< 0) { /* no translation */
898 if ((cwevent
->key
== XK_r
|| cwevent
->key
== XK_R
) && (cwevent
->state
& ControlMask
)) {
899 cwevent
->command
= e
->macro_i
< 0 ? CK_Begin_Record_Macro
: CK_End_Record_Macro
;
901 cwevent
->command
= CKeySymMod (xevent
);
902 if (cwevent
->command
> 0)
903 cwevent
->command
= CK_Macro (cwevent
->command
);
908 r
= edit_execute_key_command (e
, cwevent
->command
, cwevent
->insert
);
910 edit_update_screen (e
);
914 cwevent
->ident
= w
->ident
;
915 cwevent
->command
= xevent
->xkey
.keycode
;
916 r
= cwevent
->handled
= edit_execute_key_command (e
, xevent
->xkey
.keycode
, -1);
918 edit_update_screen (e
);
923 edit_update_screen (e
);
930 WButtonBar
*edit_bar
;
934 int column_highlighting
= 0;
936 static int edit_callback (Dlg_head
* h
, WEdit
* edit
, int msg
, int par
);
938 static int edit_mode_callback (struct Dlg_head
*h
, int id
, int msg
)
943 int edit_event (WEdit
* edit
, Gpm_Event
* event
, int *result
)
945 *result
= MOU_NORMAL
;
946 edit_update_curs_row (edit
);
947 edit_update_curs_col (edit
);
948 if (event
->type
& (GPM_DOWN
| GPM_DRAG
| GPM_UP
)) {
949 if (event
->y
> 1 && event
->x
> 0
950 && event
->x
<= edit
->num_widget_columns
951 && event
->y
<= edit
->num_widget_lines
+ 1) {
952 if (edit
->mark2
!= -1 && event
->type
& (GPM_UP
| GPM_DRAG
))
953 return 1; /* a lone up mustn't do anything */
954 if (event
->type
& (GPM_DOWN
| GPM_UP
))
955 edit_push_key_press (edit
);
956 edit_cursor_move (edit
, edit_bol (edit
, edit
->curs1
) - edit
->curs1
);
957 if (--event
->y
> (edit
->curs_row
+ 1))
958 edit_cursor_move (edit
,
959 edit_move_forward (edit
, edit
->curs1
, event
->y
- (edit
->curs_row
+ 1), 0)
961 if (event
->y
< (edit
->curs_row
+ 1))
962 edit_cursor_move (edit
,
963 +edit_move_backward (edit
, edit
->curs1
, (edit
->curs_row
+ 1) - event
->y
)
965 edit_cursor_move (edit
, (int) edit_move_forward3 (edit
, edit
->curs1
,
966 event
->x
- edit
->start_col
- 1, 0) - edit
->curs1
);
967 edit
->prev_col
= edit_get_col (edit
);
968 if (event
->type
& GPM_DOWN
) {
969 edit_mark_cmd (edit
, 1); /* reset */
972 if (!(event
->type
& GPM_DRAG
))
973 edit_mark_cmd (edit
, 0);
974 edit
->force
|= REDRAW_COMPLETELY
;
975 edit_update_curs_row (edit
);
976 edit_update_curs_col (edit
);
977 edit_update_screen (edit
);
986 int menubar_event (Gpm_Event
* event
, WMenu
* menubar
); /* menu.c */
988 int edit_mouse_event (Gpm_Event
* event
, void *x
)
991 if (edit_event ((WEdit
*) x
, event
, &result
))
994 return menubar_event (event
, edit_menubar
);
997 extern Menu EditMenuBar
[5];
999 int edit (const char *_file
, int line
)
1001 static int made_directory
= 0;
1003 int midnight_colors
[4];
1006 if (option_backup_ext_int
!= -1) {
1007 option_backup_ext
= malloc (sizeof (int) + 1);
1008 option_backup_ext
[sizeof (int)] = '\0';
1009 memcpy (option_backup_ext
, (char *) &option_backup_ext_int
, sizeof (int));
1011 if (!made_directory
) {
1012 mkdir (catstrs (home_dir
, EDIT_DIR
, 0), 0700);
1023 if (!(wedit
= edit_init (NULL
, LINES
- 2, COLS
, _file
, text
, "", 0))) {
1024 message (1, _ (" Error "), get_error_msg (""));
1027 wedit
->macro_i
= -1;
1029 /* Create a new dialog and add it widgets to it */
1030 edit_dlg
= create_dlg (0, 0, LINES
, COLS
, midnight_colors
,
1031 edit_mode_callback
, "[Internal File Editor]",
1035 edit_dlg
->raw
= 1; /*so that tab = '\t' key works */
1037 init_widget (&(wedit
->widget
), 0, 0, LINES
- 1, COLS
,
1038 (callback_fn
) edit_callback
,
1039 (destroy_fn
) edit_clean
,
1040 (mouse_h
) edit_mouse_event
, 0);
1042 widget_want_cursor (wedit
->widget
, 1);
1044 edit_bar
= buttonbar_new (1);
1047 switch (edit_key_emulation
) {
1048 case EDIT_KEY_EMULATION_NORMAL
:
1049 edit_init_menu_normal (); /* editmenu.c */
1051 case EDIT_KEY_EMULATION_EMACS
:
1052 edit_init_menu_emacs (); /* editmenu.c */
1055 edit_menubar
= menubar_new (0, 0, COLS
, EditMenuBar
, N_menus
);
1057 add_widget (edit_dlg
, wedit
);
1060 add_widget (edit_dlg
, edit_menubar
);
1062 add_widget (edit_dlg
, edit_bar
);
1063 edit_move_display (wedit
, line
- 1);
1064 edit_move_to_line (wedit
, line
- 1);
1069 edit_done_menu (); /* editmenu.c */
1071 destroy_dlg (edit_dlg
);
1076 static void edit_my_define (Dlg_head
* h
, int idx
, char *text
,
1077 void (*fn
) (WEdit
*), WEdit
* edit
)
1079 define_label_data (h
, (Widget
*) edit
, idx
, text
, (buttonbarfn
) fn
, edit
);
1083 void cmd_F1 (WEdit
* edit
)
1085 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (1));
1088 void cmd_F2 (WEdit
* edit
)
1090 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (2));
1093 void cmd_F3 (WEdit
* edit
)
1095 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (3));
1098 void cmd_F4 (WEdit
* edit
)
1100 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (4));
1103 void cmd_F5 (WEdit
* edit
)
1105 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (5));
1108 void cmd_F6 (WEdit
* edit
)
1110 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (6));
1113 void cmd_F7 (WEdit
* edit
)
1115 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (7));
1118 void cmd_F8 (WEdit
* edit
)
1120 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (8));
1123 void cmd_F9 (WEdit
* edit
)
1125 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (9));
1128 void cmd_F10 (WEdit
* edit
)
1130 send_message (edit
->widget
.parent
, (Widget
*) edit
, WIDGET_KEY
, KEY_F (10));
1133 void edit_labels (WEdit
* edit
)
1135 Dlg_head
*h
= edit
->widget
.parent
;
1137 edit_my_define (h
, 1, _ ("Help"), cmd_F1
, edit
);
1138 edit_my_define (h
, 2, _ ("Save"), cmd_F2
, edit
);
1139 edit_my_define (h
, 3, _ ("Mark"), cmd_F3
, edit
);
1140 edit_my_define (h
, 4, _ ("Replac"), cmd_F4
, edit
);
1141 edit_my_define (h
, 5, _ ("Copy"), cmd_F5
, edit
);
1142 edit_my_define (h
, 6, _ ("Move"), cmd_F6
, edit
);
1143 edit_my_define (h
, 7, _ ("Search"), cmd_F7
, edit
);
1144 edit_my_define (h
, 8, _ ("Delete"), cmd_F8
, edit
);
1145 if (!edit
->have_frame
)
1146 edit_my_define (h
, 9, _ ("PullDn"), edit_menu_cmd
, edit
);
1147 edit_my_define (h
, 10, _ ("Quit"), cmd_F10
, edit
);
1149 redraw_labels (h
, (Widget
*) edit
);
1153 long get_key_state ()
1155 return (long) get_modifier ();
1158 void edit_adjust_size (Dlg_head
* h
)
1161 WButtonBar
*edit_bar
;
1163 edit
= (WEdit
*) find_widget_type (h
, (callback_fn
) edit_callback
);
1164 edit_bar
= (WButtonBar
*) edit
->widget
.parent
->current
->next
->widget
;
1165 widget_set_size (&edit
->widget
, 0, 0, LINES
- 1, COLS
);
1166 widget_set_size (&edit_bar
->widget
, LINES
- 1, 0, 1, COLS
);
1167 widget_set_size (&edit_menubar
->widget
, 0, 0, 1, COLS
);
1169 #ifdef RESIZABLE_MENUBAR
1170 menubar_arrange (edit_menubar
);
1174 void edit_update_screen (WEdit
* e
)
1176 edit_scroll_screen_over_cursor (e
);
1178 edit_update_curs_col (e
);
1181 /* pop all events for this window for internal handling */
1184 e
->force
|= REDRAW_PAGE
;
1187 if (e
->force
& REDRAW_COMPLETELY
)
1188 e
->force
|= REDRAW_PAGE
;
1189 edit_render_keypress (e
);
1192 static int edit_callback (Dlg_head
* h
, WEdit
* e
, int msg
, int par
)
1196 e
->force
|= REDRAW_COMPLETELY
;
1200 e
->force
|= REDRAW_COMPLETELY
;
1201 e
->num_widget_lines
= LINES
- 2;
1202 e
->num_widget_columns
= COLS
;
1204 edit_update_screen (e
);
1208 if (edit_drop_hotkey_menu (e
, par
)) /* first check alt-f, alt-e, alt-s, etc for drop menus */
1210 if (!edit_translate_key (e
, 0, par
, get_key_state (), &cmd
, &ch
))
1212 edit_execute_key_command (e
, cmd
, ch
);
1213 edit_update_screen (e
);
1216 case WIDGET_COMMAND
:
1217 edit_execute_key_command (e
, par
, -1);
1218 edit_update_screen (e
);
1221 widget_move (&e
->widget
, e
->curs_row
+ EDIT_TEXT_VERTICAL_OFFSET
, e
->curs_col
+ e
->start_col
);
1224 return default_proc (h
, msg
, par
);