- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception...
[reactos.git] / rosapps / mc / edit / editwidget.c
1 /* editor initialisation and callback handler.
2
3 Copyright (C) 1996, 1997 the Free Software Foundation
4
5 Authors: 1996, 1997 Paul Sheer
6
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.
11
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.
16
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21
22 #include <config.h>
23 #include "edit.h"
24
25 #ifndef MIDNIGHT
26 #include <X11/Xmd.h> /* CARD32 */
27 #include <X11/Xatom.h>
28 #include "app_glob.c"
29 #include "coollocal.h"
30 #include "editcmddef.h"
31 #include "mousemark.h"
32 #endif
33
34
35 #ifndef MIDNIGHT
36
37 extern int EditExposeRedraw;
38 CWidget *wedit = 0;
39
40 void edit_destroy_callback (CWidget * w)
41 {
42 if (w) {
43 edit_clean (w->editor);
44 if (w->editor)
45 free (w->editor);
46 w->editor = NULL;
47 } else
48 /* NLS ? */
49 CError ("Trying to destroy non-existing editor widget.\n");
50 }
51
52 void link_hscrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * xevent, CEvent * cwevent, int whichscrbutton);
53
54 extern int option_editor_bg_normal;
55 void edit_tri_cursor (Window win);
56 /* starting_directory is for the filebrowser */
57 CWidget *CDrawEditor (const char *identifier, Window parent, int x, int y,
58 int width, int height, const char *text, const char *filename,
59 const char *starting_directory, unsigned int options, unsigned long text_size)
60 {
61 static made_directory = 0;
62 int extra_space_for_hscroll = 0;
63 CWidget *w;
64 WEdit *e;
65
66 if (options & EDITOR_HORIZ_SCROLL)
67 extra_space_for_hscroll = 8;
68
69 wedit = w = CSetupWidget (identifier, parent, x, y,
70 width + 7, height + 6, C_EDITOR_WIDGET,
71 ExposureMask | ButtonPressMask | ButtonReleaseMask | \
72 KeyPressMask | KeyReleaseMask | ButtonMotionMask | \
73 PropertyChangeMask | StructureNotifyMask | \
74 EnterWindowMask | LeaveWindowMask, color_palette (option_editor_bg_normal), 1);
75 edit_tri_cursor (w->winid);
76 w->options = options | WIDGET_TAKES_SELECTION;
77
78 w->destroy = edit_destroy_callback;
79 if (filename)
80 w->label = strdup (filename);
81 else
82 w->label = strdup ("");
83
84 if (!made_directory) {
85 mkdir (catstrs (home_dir, EDIT_DIR, 0), 0700);
86 made_directory = 1;
87 }
88 e = w->editor = CMalloc (sizeof (WEdit));
89 if (!w->editor) {
90 /* Not essential to translate */
91 CError (_ ("Error initialising editor.\n"));
92 return 0;
93 }
94 w->editor->widget = w;
95 e = w->editor = edit_init (e, height / FONT_PIX_PER_LINE, width / FONT_MEAN_WIDTH, filename, text, starting_directory, text_size);
96 if (!e) {
97 CDestroyWidget (w->ident);
98 return 0;
99 }
100 e->macro_i = -1;
101 e->widget = w;
102
103 set_hint_pos (x + width + 7 + WIDGET_SPACING, y + height + 6 + WIDGET_SPACING + extra_space_for_hscroll);
104 if (extra_space_for_hscroll) {
105 w->hori_scrollbar = CDrawHorizontalScrollbar (catstrs (identifier, ".hsc", 0), parent,
106 x, y + height + 6, width + 6, 12, 0, 0);
107 CSetScrollbarCallback (w->hori_scrollbar->ident, w->ident, link_hscrollbar_to_editor);
108 }
109 if (!(options & EDITOR_NO_TEXT))
110 CDrawText (catstrs (identifier, ".text", 0), parent, x, y + height + 6 + WIDGET_SPACING + extra_space_for_hscroll, "%s", e->filename);
111 if (!(options & EDITOR_NO_SCROLL)) {
112 w->vert_scrollbar = CDrawVerticalScrollbar (catstrs (identifier, ".vsc", 0), parent,
113 x + width + 7 + WIDGET_SPACING, y, height + 6, 20, 0, 0);
114 CSetScrollbarCallback (w->vert_scrollbar->ident, w->ident, link_scrollbar_to_editor);
115 }
116 return w;
117 }
118
119 void update_scroll_bars (WEdit * e)
120 {
121 int i, x1, x2;
122 CWidget *scroll;
123 scroll = e->widget->vert_scrollbar;
124 if (scroll) {
125 i = e->total_lines - e->start_line + 1;
126 if (i > e->num_widget_lines)
127 i = e->num_widget_lines;
128 if (e->total_lines) {
129 x1 = (double) 65535.0 *e->start_line / (e->total_lines + 1);
130 x2 = (double) 65535.0 *i / (e->total_lines + 1);
131 } else {
132 x1 = 0;
133 x2 = 65535;
134 }
135 if (x1 != scroll->firstline || x2 != scroll->numlines) {
136 scroll->firstline = x1;
137 scroll->numlines = x2;
138 EditExposeRedraw = 1;
139 render_scrollbar (scroll);
140 EditExposeRedraw = 0;
141 }
142 }
143 scroll = e->widget->hori_scrollbar;
144 if (scroll) {
145 i = e->max_column - (-e->start_col) + 1;
146 if (i > e->num_widget_columns * FONT_MEAN_WIDTH)
147 i = e->num_widget_columns * FONT_MEAN_WIDTH;
148 x1 = (double) 65535.0 *(-e->start_col) / (e->max_column + 1);
149 x2 = (double) 65535.0 *i / (e->max_column + 1);
150 if (x1 != scroll->firstline || x2 != scroll->numlines) {
151 scroll->firstline = x1;
152 scroll->numlines = x2;
153 EditExposeRedraw = 1;
154 render_scrollbar (scroll);
155 EditExposeRedraw = 0;
156 }
157 }
158 }
159
160 /* returns the position in the edit buffer of a window click */
161 long edit_get_click_pos (WEdit * edit, int x, int y)
162 {
163 long click;
164 /* (1) goto to left margin */
165 click = edit_bol (edit, edit->curs1);
166
167 /* (1) move up or down */
168 if (y > (edit->curs_row + 1))
169 click = edit_move_forward (edit, click, y - (edit->curs_row + 1), 0);
170 if (y < (edit->curs_row + 1))
171 click = edit_move_backward (edit, click, (edit->curs_row + 1) - y);
172
173 /* (3) move right to x pos */
174 click = edit_move_forward3 (edit, click, x - edit->start_col - 1, 0);
175 return click;
176 }
177
178 void edit_translate_xy (int xs, int ys, int *x, int *y)
179 {
180 *x = xs - EDIT_TEXT_HORIZONTAL_OFFSET;
181 *y = (ys - EDIT_TEXT_VERTICAL_OFFSET - option_text_line_spacing / 2 - 1) / FONT_PIX_PER_LINE + 1;
182 }
183
184 extern int just_dropped_something;
185
186 static void mouse_redraw (WEdit * edit, long click)
187 {
188 edit->force |= REDRAW_PAGE | REDRAW_LINE;
189 edit_update_curs_row (edit);
190 edit_update_curs_col (edit);
191 edit->prev_col = edit_get_col (edit);
192 edit_update_screen (edit);
193 edit->search_start = click;
194 }
195
196 static void xy (int x, int y, int *x_return, int *y_return)
197 {
198 edit_translate_xy (x, y, x_return, y_return);
199 }
200
201 static long cp (WEdit *edit, int x, int y)
202 {
203 return edit_get_click_pos (edit, x, y);
204 }
205
206 /* return 1 if not marked */
207 static int marks (WEdit * edit, long *start, long *end)
208 {
209 return eval_marks (edit, start, end);
210 }
211
212 int column_highlighting = 0;
213
214 static int erange (WEdit * edit, long start, long end, int click)
215 {
216 if (column_highlighting) {
217 int x;
218 x = edit_move_forward3 (edit, edit_bol (edit, click), 0, click);
219 if ((x >= edit->column1 && x < edit->column2)
220 || (x > edit->column2 && x <= edit->column1))
221 return (start <= click && click < end);
222 else
223 return 0;
224 }
225 return (start <= click && click < end);
226 }
227
228 static void fin_mark (WEdit *edit)
229 {
230 if (edit->mark2 < 0)
231 edit_mark_cmd (edit, 0);
232 }
233
234 static void move_mark (WEdit *edit)
235 {
236 edit_mark_cmd (edit, 1);
237 edit_mark_cmd (edit, 0);
238 }
239
240 static void release_mark (WEdit *edit, XEvent *event)
241 {
242 if (edit->mark2 < 0)
243 edit_mark_cmd (edit, 0);
244 else
245 edit_mark_cmd (edit, 1);
246 if (edit->mark1 != edit->mark2) {
247 edit_get_selection (edit);
248 XSetSelectionOwner (CDisplay, XA_PRIMARY, edit->widget->winid, event->xbutton.time);
249 }
250 }
251
252 static char *get_block (WEdit * edit, long start_mark, long end_mark, int *type, int *l)
253 {
254 char *t;
255 t = (char *) edit_get_block (edit, start_mark, end_mark, l);
256 if (strlen (t) < *l)
257 *type = DndRawData; /* if there are nulls in the data, send as raw */
258 else
259 *type = DndText; /* else send as text */
260 return t;
261 }
262
263 static void move (WEdit *edit, long click, int y)
264 {
265 edit_cursor_move (edit, click - edit->curs1);
266 }
267
268 static void dclick (WEdit *edit, XEvent *event)
269 {
270 edit_mark_cmd (edit, 1);
271 edit_right_word_move (edit);
272 edit_mark_cmd (edit, 0);
273 edit_left_word_move (edit);
274 release_mark (edit, event);
275 }
276
277 static void redraw (WEdit *edit, long click)
278 {
279 mouse_redraw (edit, click);
280 }
281
282 static void edit_mouse_mark (WEdit * edit, XEvent * event, CEvent * ce)
283 {
284 edit_update_curs_row (edit);
285 edit_update_curs_col (edit);
286 if (event->type != MotionNotify) {
287 edit_push_action (edit, KEY_PRESS + edit->start_display);
288 if (edit->mark2 == -1)
289 edit_push_action (edit, MARK_1 + edit->mark1); /* mark1 must be following the cursor */
290 }
291 if (event->type == ButtonPress) {
292 edit->highlight = 0;
293 edit->found_len = 0;
294 }
295 mouse_mark (
296 (void *) edit,
297 event,
298 ce,
299 (void (*) (int, int, int *, int *)) xy,
300 (long (*) (void *, int, int)) cp,
301 (int (*) (void *, long *, long *)) marks,
302 (int (*) (void *, long, long, long)) erange,
303 (void (*) (void *)) fin_mark,
304 (void (*) (void *)) move_mark,
305 (void (*) (void *, XEvent *)) release_mark,
306 (char * (*) (void *, long, long, int *, int *)) get_block,
307 (void (*) (void *, long, int)) move,
308 0,
309 (void (*) (void *, XEvent *)) dclick,
310 (void (*) (void *, long)) redraw
311 );
312 }
313
314 void link_scrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * xevent, CEvent * cwevent, int whichscrbutton)
315 {
316 int i, start_line;
317 WEdit *e;
318 e = editor->editor;
319 if (!e)
320 return;
321 if (!e->widget->vert_scrollbar)
322 return;
323 start_line = e->start_line;
324 if ((xevent->type == ButtonRelease || xevent->type == MotionNotify) && whichscrbutton == 3) {
325 edit_move_display (e, (double) scrollbar->firstline * e->total_lines / 65535.0 + 1);
326 } else if (xevent->type == ButtonPress && (cwevent->button == Button1 || cwevent->button == Button2)) {
327 switch (whichscrbutton) {
328 case 1:
329 edit_move_display (e, e->start_line - e->num_widget_lines + 1);
330 break;
331 case 2:
332 edit_move_display (e, e->start_line - 1);
333 break;
334 case 5:
335 edit_move_display (e, e->start_line + 1);
336 break;
337 case 4:
338 edit_move_display (e, e->start_line + e->num_widget_lines - 1);
339 break;
340 }
341 }
342 if (e->total_lines)
343 scrollbar->firstline = (double) 65535.0 *e->start_line / (e->total_lines + 1);
344 else
345 scrollbar->firstline = 0;
346 i = e->total_lines - e->start_line + 1;
347 if (i > e->num_widget_lines)
348 i = e->num_widget_lines;
349 if (e->total_lines)
350 scrollbar->numlines = (double) 65535.0 *i / (e->total_lines + 1);
351 else
352 scrollbar->numlines = 65535;
353 if (start_line != e->start_line) {
354 e->force |= REDRAW_PAGE | REDRAW_LINE;
355 set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
356 if (CCheckWindowEvent (xevent->xany.window, ButtonReleaseMask | ButtonMotionMask, 0))
357 return;
358 }
359 if (e->force) {
360 edit_render_keypress (e);
361 edit_status (e);
362 }
363 }
364
365 void link_hscrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * xevent, CEvent * cwevent, int whichscrbutton)
366 {
367 int i, start_col;
368 WEdit *e;
369 e = editor->editor;
370 if (!e)
371 return;
372 if (!e->widget->hori_scrollbar)
373 return;
374 start_col = (-e->start_col);
375 if ((xevent->type == ButtonRelease || xevent->type == MotionNotify) && whichscrbutton == 3) {
376 e->start_col = (double) scrollbar->firstline * e->max_column / 65535.0 + 1;
377 e->start_col -= e->start_col % FONT_MEAN_WIDTH;
378 if (e->start_col < 0)
379 e->start_col = 0;
380 e->start_col = (-e->start_col);
381 } else if (xevent->type == ButtonPress && (cwevent->button == Button1 || cwevent->button == Button2)) {
382 switch (whichscrbutton) {
383 case 1:
384 edit_scroll_left (e, (e->num_widget_columns - 1) * FONT_MEAN_WIDTH);
385 break;
386 case 2:
387 edit_scroll_left (e, FONT_MEAN_WIDTH);
388 break;
389 case 5:
390 edit_scroll_right (e, FONT_MEAN_WIDTH);
391 break;
392 case 4:
393 edit_scroll_right (e, (e->num_widget_columns - 1) * FONT_MEAN_WIDTH);
394 break;
395 }
396 }
397 scrollbar->firstline = (double) 65535.0 *(-e->start_col) / (e->max_column + 1);
398 i = e->max_column - (-e->start_col) + 1;
399 if (i > e->num_widget_columns * FONT_MEAN_WIDTH)
400 i = e->num_widget_columns * FONT_MEAN_WIDTH;
401 scrollbar->numlines = (double) 65535.0 *i / (e->max_column + 1);
402 if (start_col != (-e->start_col)) {
403 e->force |= REDRAW_PAGE | REDRAW_LINE;
404 set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
405 if (CCheckWindowEvent (xevent->xany.window, ButtonReleaseMask | ButtonMotionMask, 0))
406 return;
407 }
408 if (e->force) {
409 edit_render_keypress (e);
410 edit_status (e);
411 }
412 }
413
414 /*
415 This section comes from rxvt-2.21b1/src/screen.c by
416 Robert Nation <nation@rocket.sanders.lockheed.com> &
417 mods by mj olesen <olesen@me.QueensU.CA>
418
419 Changes made for cooledit
420 */
421 void selection_send (XSelectionRequestEvent * rq)
422 {
423 XEvent ev;
424 static Atom xa_targets = None;
425 if (xa_targets == None)
426 xa_targets = XInternAtom (CDisplay, "TARGETS", False);
427
428 ev.xselection.type = SelectionNotify;
429 ev.xselection.property = None;
430 ev.xselection.display = rq->display;
431 ev.xselection.requestor = rq->requestor;
432 ev.xselection.selection = rq->selection;
433 ev.xselection.target = rq->target;
434 ev.xselection.time = rq->time;
435
436 if (rq->target == xa_targets) {
437 /*
438 * On some systems, the Atom typedef is 64 bits wide.
439 * We need to have a typedef that is exactly 32 bits wide,
440 * because a format of 64 is not allowed by the X11 protocol.
441 */
442 typedef CARD32 Atom32;
443
444 Atom32 target_list[2];
445
446 target_list[0] = (Atom32) xa_targets;
447 target_list[1] = (Atom32) XA_STRING;
448
449 XChangeProperty (CDisplay, rq->requestor, rq->property,
450 xa_targets, 8 * sizeof (target_list[0]), PropModeReplace,
451 (unsigned char *) target_list,
452 sizeof (target_list) / sizeof (target_list[0]));
453 ev.xselection.property = rq->property;
454 } else if (rq->target == XA_STRING) {
455 XChangeProperty (CDisplay, rq->requestor, rq->property,
456 XA_STRING, 8, PropModeReplace,
457 selection.text, selection.len);
458 ev.xselection.property = rq->property;
459 }
460 XSendEvent (CDisplay, rq->requestor, False, 0, &ev);
461 }
462
463 /*{{{ paste selection */
464
465 /*
466 * Respond to a notification that a primary selection has been sent
467 */
468 void paste_prop (void *data, void (*insert) (void *, int), Window win, unsigned prop, int delete)
469 {
470 long nread;
471 unsigned long bytes_after;
472
473 if (prop == None)
474 return;
475
476 nread = 0;
477 do {
478 unsigned char *s;
479 Atom actual_type;
480 int actual_fmt, i;
481 unsigned long nitems;
482
483 if (XGetWindowProperty (CDisplay, win, prop,
484 nread / 4, 65536, delete,
485 AnyPropertyType, &actual_type, &actual_fmt,
486 &nitems, &bytes_after,
487 &s) != Success) {
488 XFree (s);
489 return;
490 }
491 nread += nitems;
492 for (i = 0; i < nitems; i++)
493 (*insert) (data, s[i]);
494 XFree (s);
495 } while (bytes_after);
496 }
497
498 void selection_paste (WEdit * edit, Window win, unsigned prop, int delete)
499 {
500 long c;
501 c = edit->curs1;
502 paste_prop ((void *) edit,
503 (void (*)(void *, int)) edit_insert,
504 win, prop, delete);
505 edit_cursor_move (edit, c - edit->curs1);
506 edit->force |= REDRAW_COMPLETELY | REDRAW_LINE;
507 }
508
509 /*}}} */
510
511 void selection_clear (void)
512 {
513 selection.text = 0;
514 selection.len = 0;
515 }
516
517 void edit_update_screen (WEdit * e)
518 {
519 if (!e)
520 return;
521 if (!e->force)
522 return;
523
524 edit_scroll_screen_over_cursor (e);
525 edit_update_curs_row (e);
526 edit_update_curs_col (e);
527 update_scroll_bars (e);
528 edit_status (e);
529
530 if (e->force & REDRAW_COMPLETELY)
531 e->force |= REDRAW_PAGE;
532
533 /* pop all events for this window for internal handling */
534 if (e->force & (REDRAW_CHAR_ONLY | REDRAW_COMPLETELY)) {
535 edit_render_keypress (e);
536 } else if (CCheckWindowEvent (e->widget->winid, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask, 0)
537 || CKeyPending ()) {
538 e->force |= REDRAW_PAGE;
539 return;
540 } else {
541 edit_render_keypress (e);
542 }
543 }
544
545 extern int space_width;
546
547 static void edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width)
548 {
549 long cursor;
550 int i, col;
551 cursor = edit->curs1;
552 col = edit_get_col (edit);
553 for (i = 0; i < size; i++) {
554 if (data[i] == '\n') { /* fill in and move to next line */
555 int l;
556 long p;
557 if (edit_get_byte (edit, edit->curs1) != '\n') {
558 l = width - (edit_get_col (edit) - col);
559 while (l > 0) {
560 edit_insert (edit, ' ');
561 l -= space_width;
562 }
563 }
564 for (p = edit->curs1;; p++) {
565 if (p == edit->last_byte)
566 edit_insert_ahead (edit, '\n');
567 if (edit_get_byte (edit, p) == '\n') {
568 p++;
569 break;
570 }
571 }
572 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
573 l = col - edit_get_col (edit);
574 while (l >= space_width) {
575 edit_insert (edit, ' ');
576 l -= space_width;
577 }
578 continue;
579 }
580 edit_insert (edit, data[i]);
581 }
582 edit_cursor_move (edit, cursor - edit->curs1);
583 }
584
585 #define free_data if (data) {free(data);data=0;}
586
587 /* handles drag and drop */
588 void handle_client_message (CWidget * w, XEvent * xevent, CEvent * cwevent)
589 {
590 int data_type;
591 unsigned char *data;
592 unsigned long size;
593 int xs, ys;
594 long start_line;
595 int x, y, r, deleted = 0;
596 long click;
597 unsigned int state;
598 long start_mark = 0, end_mark = 0;
599 WEdit *e = w->editor;
600
601 /* see just below for a comment on what this is for: */
602 if (CIsDropAcknowledge (xevent, &state) != DndNotDnd) {
603 if (!(state & Button1Mask) && just_dropped_something) {
604 edit_push_action (e, KEY_PRESS + e->start_display);
605 edit_block_delete_cmd (e);
606 }
607 return;
608 }
609 data_type = CGetDrop (xevent, &data, &size, &xs, &ys);
610
611 if (data_type == DndNotDnd || xs < 0 || ys < 0 || xs >= w->width || ys >= w->height) {
612 free_data;
613 return;
614 }
615 edit_translate_xy (xs, ys, &x, &y);
616 click = edit_get_click_pos (e, x, y);
617
618 r = eval_marks (e, &start_mark, &end_mark);
619 /* musn't be able to drop into a block, otherwise a single click will copy a block: */
620 if (r)
621 goto fine;
622 if (start_mark > click || click >= end_mark)
623 goto fine;
624 if (column_highlighting) {
625 if (!((x >= e->column1 && x < e->column2)
626 || (x > e->column2 && x <= e->column1)))
627 goto fine;
628 }
629 free_data;
630 return;
631 fine:
632 edit_push_action (e, KEY_PRESS + e->start_display);
633
634 /* drops to the same window moving to the left: */
635 start_line = e->start_line;
636 if (xevent->xclient.data.l[2] == xevent->xclient.window && !(xevent->xclient.data.l[1] & Button1Mask))
637 if ((column_highlighting && x < max (e->column1, e->column2)) || !column_highlighting) {
638 edit_block_delete_cmd (e);
639 deleted = 1;
640 }
641 edit_update_curs_row (e);
642 edit_move_display (e, start_line);
643 click = edit_get_click_pos (e, x, y); /* click pos changes with edit_block_delete_cmd() */
644 edit_cursor_move (e, click - e->curs1);
645 if (data_type == DndFile) {
646 edit_insert_file (e, (char *) data);
647 } else if (data_type != DndFiles) {
648 if (dnd_null_term_type (data_type)) {
649 int len;
650 len = strlen ((char *) data);
651 size = min (len, size);
652 }
653 if (column_highlighting) {
654 edit_insert_column_of_text (e, data, size, abs (e->column2 - e->column1));
655 } else {
656 while (size--)
657 edit_insert_ahead (e, data[size]);
658 }
659 } else {
660 while (size--)
661 edit_insert_ahead (e, data[size] ? data[size] : '\n');
662 }
663
664 /* drops to the same window moving to the right: */
665 if (xevent->xclient.data.l[2] == xevent->xclient.window && !(xevent->xclient.data.l[1] & Button1Mask))
666 if (column_highlighting && !deleted)
667 edit_block_delete_cmd (e);
668
669 /* The drop has now been successfully recieved. We can now send an acknowledge
670 event back to the window that send the data. When this window recieves
671 the acknowledge event, the app can decide whether or not to delete the data.
672 This allows text to be safely moved betweem text windows without the
673 risk of data being lost. In our case, drag with button1 is a copy
674 drag, while drag with any other button is a move drag (i.e. the sending
675 application must delete its selection after recieving an acknowledge
676 event). We must not, however, send an acknowledge signal if a filelist
677 (for example) was passed to us, since the sender might take this to
678 mean that all those files can be deleted! The two types we can acknowledge
679 are: */
680 if (xevent->xclient.data.l[2] != xevent->xclient.window) /* drops to the same window */
681 if (data_type == DndText || data_type == DndRawData)
682 CDropAcknowledge (xevent);
683 e->force |= REDRAW_COMPLETELY | REDRAW_LINE;
684 free_data;
685 }
686
687 int eh_editor (CWidget * w, XEvent * xevent, CEvent * cwevent)
688 {
689 WEdit *e = w->editor;
690 int r = 0;
691 static int old_tab_spacing = -1;
692
693 if (!e)
694 return 0;
695
696 if (old_tab_spacing != option_tab_spacing)
697 e->force |= REDRAW_COMPLETELY + REDRAW_LINE;
698 old_tab_spacing = option_tab_spacing;
699
700 if (xevent->type == KeyPress) {
701 if (xevent->xkey.keycode == 0x31 && xevent->xkey.state == 0xD) {
702 CSetColor (color_palette (18));
703 CRectangle (w->winid, 0, 0, w->width, w->height);
704 }
705 }
706 switch (xevent->type) {
707 case SelectionNotify:
708 selection_paste (e, xevent->xselection.requestor, xevent->xselection.property, True);
709 r = 1;
710 break;
711 case SelectionRequest:
712 selection_send (&(xevent->xselectionrequest));
713 return 1;
714 /* case SelectionClear: ---> This is handled by coolnext.c: CNextEvent() */
715 case ClientMessage:
716 handle_client_message (w, xevent, cwevent);
717 r = 1;
718 break;
719 case ButtonPress:
720 CFocus (w);
721 edit_render_tidbits (w);
722 case ButtonRelease:
723 if (xevent->xbutton.state & ControlMask)
724 column_highlighting = 1;
725 else
726 column_highlighting = 0;
727 case MotionNotify:
728 if (!xevent->xmotion.state && xevent->type == MotionNotify)
729 return 0;
730 resolve_button (xevent, cwevent);
731 edit_mouse_mark (e, xevent, cwevent);
732 break;
733 case Expose:
734 edit_render_expose (e, &(xevent->xexpose));
735 return 1;
736 case FocusIn:
737 CSetCursorColor (e->overwrite ? color_palette (24) : color_palette (19));
738 case FocusOut:
739 edit_render_tidbits (w);
740 e->force |= REDRAW_CHAR_ONLY | REDRAW_LINE;
741 edit_render_keypress (e);
742 return 1;
743 break;
744 case KeyRelease:
745 if (column_highlighting) {
746 column_highlighting = 0;
747 e->force = REDRAW_COMPLETELY | REDRAW_LINE;
748 edit_mark_cmd (e, 1);
749 }
750 break;
751 case KeyPress:
752 cwevent->ident = w->ident;
753 if (!cwevent->command && cwevent->insert < 0) { /* no translation */
754 if ((cwevent->key == XK_r || cwevent->key == XK_R) && (cwevent->state & ControlMask)) {
755 cwevent->command = e->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
756 } else {
757 cwevent->command = CKeySymMod (xevent);
758 if (cwevent->command > 0)
759 cwevent->command = CK_Macro (cwevent->command);
760 else
761 break;
762 }
763 }
764 r = edit_execute_key_command (e, cwevent->command, cwevent->insert);
765 if (r)
766 edit_update_screen (e);
767 return r;
768 break;
769 case EditorCommand:
770 cwevent->ident = w->ident;
771 cwevent->command = xevent->xkey.keycode;
772 r = cwevent->handled = edit_execute_key_command (e, xevent->xkey.keycode, -1);
773 break;
774 default:
775 return 0;
776 }
777 edit_update_screen (e);
778 return r;
779 }
780
781 #else
782
783 WEdit *wedit;
784 WButtonBar *edit_bar;
785 Dlg_head *edit_dlg;
786 WMenu *edit_menubar;
787
788 int column_highlighting = 0;
789
790 static int edit_callback (Dlg_head * h, WEdit * edit, int msg, int par);
791
792 static int edit_mode_callback (struct Dlg_head *h, int id, int msg)
793 {
794 return 0;
795 }
796
797 int edit_event (WEdit * edit, Gpm_Event * event, int *result)
798 {
799 *result = MOU_NORMAL;
800 edit_update_curs_row (edit);
801 edit_update_curs_col (edit);
802 if (event->type & (GPM_DOWN | GPM_DRAG | GPM_UP)) {
803 if (event->y > 1 && event->x > 0
804 && event->x <= edit->num_widget_columns
805 && event->y <= edit->num_widget_lines + 1) {
806 if (edit->mark2 != -1 && event->type & (GPM_UP | GPM_DRAG))
807 return 1; /* a lone up mustn't do anything */
808 if (event->type & (GPM_DOWN | GPM_UP))
809 edit_push_key_press (edit);
810 edit_cursor_move (edit, edit_bol (edit, edit->curs1) - edit->curs1);
811 if (--event->y > (edit->curs_row + 1))
812 edit_cursor_move (edit,
813 edit_move_forward (edit, edit->curs1, event->y - (edit->curs_row + 1), 0)
814 - edit->curs1);
815 if (event->y < (edit->curs_row + 1))
816 edit_cursor_move (edit,
817 +edit_move_backward (edit, edit->curs1, (edit->curs_row + 1) - event->y)
818 - edit->curs1);
819 edit_cursor_move (edit, (int) edit_move_forward3 (edit, edit->curs1,
820 event->x - edit->start_col - 1, 0) - edit->curs1);
821 edit->prev_col = edit_get_col (edit);
822 if (event->type & GPM_DOWN) {
823 edit_mark_cmd (edit, 1); /* reset */
824 edit->highlight = 0;
825 }
826 if (!(event->type & GPM_DRAG))
827 edit_mark_cmd (edit, 0);
828 edit->force |= REDRAW_COMPLETELY;
829 edit_update_curs_row (edit);
830 edit_update_curs_col (edit);
831 edit_update_screen (edit);
832 return 1;
833 }
834 }
835 return 0;
836 }
837
838
839
840 int menubar_event (Gpm_Event * event, WMenu * menubar); /* menu.c */
841
842 int edit_mouse_event (Gpm_Event * event, void *x)
843 {
844 int result;
845 if (edit_event ((WEdit *) x, event, &result))
846 return result;
847 else
848 return menubar_event (event, edit_menubar);
849 }
850
851 extern Menu EditMenuBar[5];
852
853 int edit (const char *_file, int line)
854 {
855 static int made_directory = 0;
856 int framed = 0;
857 int midnight_colors[4];
858 char *text = 0;
859
860 if (option_backup_ext_int != -1) {
861 option_backup_ext = malloc (sizeof(int) + 1);
862 option_backup_ext[sizeof(int)] = '\0';
863 memcpy (option_backup_ext, (char *) &option_backup_ext_int, sizeof (int));
864 }
865
866 if (!made_directory) {
867 mkdir (catstrs (home_dir, EDIT_DIR, 0), 0700);
868 made_directory = 1;
869 }
870 if (_file) {
871 if (!(*_file)) {
872 _file = 0;
873 text = "";
874 }
875 } else
876 text = "";
877
878 if (!(wedit = edit_init (NULL, LINES - 2, COLS, _file, text, "", 0))) {
879 message (1, _(" Error "), get_error_msg (""));
880 return 0;
881 }
882 wedit->macro_i = -1;
883
884 /* Create a new dialog and add it widgets to it */
885 edit_dlg = create_dlg (0, 0, LINES, COLS, midnight_colors,
886 edit_mode_callback, "[Internal File Editor]",
887 "edit",
888 DLG_NONE);
889
890 edit_dlg->raw = 1; /*so that tab = '\t' key works */
891
892 init_widget (&(wedit->widget), 0, 0, LINES - 1, COLS,
893 (callback_fn) edit_callback,
894 (destroy_fn) edit_clean,
895 (mouse_h) edit_mouse_event, 0);
896
897 widget_want_cursor (wedit->widget, 1);
898
899 edit_bar = buttonbar_new (1);
900
901 if (!framed) {
902 switch (edit_key_emulation) {
903 case EDIT_KEY_EMULATION_NORMAL:
904 edit_init_menu_normal (); /* editmenu.c */
905 break;
906 case EDIT_KEY_EMULATION_EMACS:
907 edit_init_menu_emacs (); /* editmenu.c */
908 break;
909 }
910 edit_menubar = menubar_new (0, 0, COLS, EditMenuBar, N_menus);
911 }
912 add_widget (edit_dlg, wedit);
913
914 if (!framed)
915 add_widget (edit_dlg, edit_menubar);
916
917 add_widget (edit_dlg, edit_bar);
918 edit_move_display (wedit, line - 1);
919 edit_move_to_line (wedit, line - 1);
920
921 run_dlg (edit_dlg);
922
923 if (!framed)
924 edit_done_menu (); /* editmenu.c */
925
926 destroy_dlg (edit_dlg);
927
928 return 1;
929 }
930
931 static void edit_my_define (Dlg_head * h, int idx, char *text,
932 void (*fn) (WEdit *), WEdit * edit)
933 {
934 define_label_data (h, (Widget *) edit, idx, text, (buttonbarfn) fn, edit);
935 }
936
937
938 void cmd_F1 (WEdit * edit)
939 {
940 send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (1));
941 }
942
943 void cmd_F2 (WEdit * edit)
944 {
945 send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (2));
946 }
947
948 void cmd_F3 (WEdit * edit)
949 {
950 send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (3));
951 }
952
953 void cmd_F4 (WEdit * edit)
954 {
955 send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (4));
956 }
957
958 void cmd_F5 (WEdit * edit)
959 {
960 send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (5));
961 }
962
963 void cmd_F6 (WEdit * edit)
964 {
965 send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (6));
966 }
967
968 void cmd_F7 (WEdit * edit)
969 {
970 send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (7));
971 }
972
973 void cmd_F8 (WEdit * edit)
974 {
975 send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (8));
976 }
977
978 void cmd_F9 (WEdit * edit)
979 {
980 send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (9));
981 }
982
983 void cmd_F10 (WEdit * edit)
984 {
985 send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (10));
986 }
987
988 void edit_labels (WEdit * edit)
989 {
990 Dlg_head *h = edit->widget.parent;
991
992 edit_my_define (h, 1, _("Help"), cmd_F1, edit);
993 edit_my_define (h, 2, _("Save"), cmd_F2, edit);
994 edit_my_define (h, 3, _("Mark"), cmd_F3, edit);
995 edit_my_define (h, 4, _("Replac"), cmd_F4, edit);
996 edit_my_define (h, 5, _("Copy"), cmd_F5, edit);
997 edit_my_define (h, 6, _("Move"), cmd_F6, edit);
998 edit_my_define (h, 7, _("Search"), cmd_F7, edit);
999 edit_my_define (h, 8, _("Delete"), cmd_F8, edit);
1000 if (!edit->have_frame)
1001 edit_my_define (h, 9, _("PullDn"), edit_menu_cmd, edit);
1002 edit_my_define (h, 10, _("Quit"), cmd_F10, edit);
1003
1004 redraw_labels (h, (Widget *) edit);
1005 }
1006
1007
1008 long get_key_state ()
1009 {
1010 return (long) get_modifier ();
1011 }
1012
1013 void edit_adjust_size (Dlg_head * h)
1014 {
1015 WEdit *edit;
1016 WButtonBar *edit_bar;
1017
1018 edit = (WEdit *) find_widget_type (h, (callback_fn) edit_callback);
1019 edit_bar = (WButtonBar *) edit->widget.parent->current->next->widget;
1020 widget_set_size (&edit->widget, 0, 0, LINES - 1, COLS);
1021 widget_set_size (&edit_bar->widget, LINES - 1, 0, 1, COLS);
1022 widget_set_size (&edit_menubar->widget, 0, 0, 1, COLS);
1023
1024 #ifdef RESIZABLE_MENUBAR
1025 menubar_arrange(edit_menubar);
1026 #endif
1027 }
1028
1029 void edit_update_screen (WEdit * e)
1030 {
1031 edit_scroll_screen_over_cursor (e);
1032
1033 edit_update_curs_col (e);
1034 edit_status (e);
1035
1036 /* pop all events for this window for internal handling */
1037
1038 if (!is_idle ()) {
1039 e->force |= REDRAW_PAGE;
1040 return;
1041 }
1042 if (e->force & REDRAW_COMPLETELY)
1043 e->force |= REDRAW_PAGE;
1044 edit_render_keypress (e);
1045 }
1046
1047 static int edit_callback (Dlg_head * h, WEdit * e, int msg, int par)
1048 {
1049 switch (msg) {
1050 case WIDGET_INIT:
1051 e->force |= REDRAW_COMPLETELY;
1052 edit_labels (e);
1053 break;
1054 case WIDGET_DRAW:
1055 e->force |= REDRAW_COMPLETELY;
1056 e->num_widget_lines = LINES - 2;
1057 e->num_widget_columns = COLS;
1058 case WIDGET_FOCUS:
1059 edit_update_screen (e);
1060 return 1;
1061 case WIDGET_KEY:{
1062 int cmd, ch;
1063 if (edit_drop_hotkey_menu (e, par)) /* first check alt-f, alt-e, alt-s, etc for drop menus */
1064 return 1;
1065 if (!edit_translate_key (e, 0, par, get_key_state (), &cmd, &ch))
1066 return 0;
1067 edit_execute_key_command (e, cmd, ch);
1068 edit_update_screen (e);
1069 }
1070 return 1;
1071 case WIDGET_COMMAND:
1072 edit_execute_key_command (e, par, -1);
1073 edit_update_screen (e);
1074 return 1;
1075 case WIDGET_CURSOR:
1076 widget_move (&e->widget, e->curs_row + EDIT_TEXT_VERTICAL_OFFSET, e->curs_col + e->start_col);
1077 return 1;
1078 }
1079 return default_proc (h, msg, par);
1080 }
1081
1082 #endif