1 /*
2 | xif.c
3 | $Revision $
4 */
5
6 /*
7 | Copyright (c) 1987, 1988, 1991 - 1996, 2001, 2009, 2010 Hugh Mahon.
8 */
9
10 #include "Xcurse.h"
11 #include <X11/Xutil.h>
12 #include <X11/cursorfont.h>
13
14 #include "aee.h"
15
16 #include <sys/time.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19
20 /*
21 | definitions for xif.c
22 */
23
24 char num_string[10];
25 int in_char;
26
27 Cursor ae_cursor;
28 Cursor blank_cursor;
29
30 Pixmap blank_pix;
31
32 int cursor_on;
33
34 char *aeMenuTitle = "ae menu";
35 char *aemenuitems[] = {
36 "commands",
37 "functions",
38 "help",
39 "settings",
40 "file operations",
41 "search/replace",
42 "mark/paste text"
43 };
44
45 char *file_menutitle = "file operations";
46 char *file_menuitems[] = {
47 "read file",
48 "write file"
49 };
50
51 char *sr_menutitle = "search/replace";
52 char *sr_menuitems[] = {
53 "search for ...",
54 "search",
55 "replace"
56 };
57
58 char *mp_menutitle = "mark/paste text";
59 char *mp_menuitems[] = {
60 "mark text",
61 "mark append",
62 "mark prefix",
63 "copy",
64 "cut",
65 "paste"
66 };
67
68 char *com_menutitle = "commands";
69 char *com_menuitems[] = {
70 "buffer (create/move to)",
71 "define key",
72 "character",
73 "delete current buffer",
74 "current line number is",
75 "resequence line numbers",
76 "exit (save changes)",
77 "quit (no changes)"
78 };
79
80 char *com_strings[] = {
81 "buffer ", "define ", "character", "delete",
82 "line", "resequence", "exit", "quit"
83 };
84
85 char *func_menutitle = "functions";
86 char *func_menuitems[] = {
87 "next page",
88 "previous page",
89 "next buffer",
90 "previous buffer",
91 "delete line",
92 "delete word",
93 "delete char",
94 "undelete line",
95 "undelete word",
96 "undelete char",
97 "begin of line",
98 "end of line",
99 "begin of text",
100 "end of text",
101 "insert line",
102 "next line",
103 "next word",
104 "previous word",
105 "match () [] <> {}",
106 "redraw screen"
107 };
108
109 XFontStruct *panelfont;
110
111 /*
112 | definitions from Xcurse.c
113 */
114
115 extern int fontheight, fontwidth;
116 extern Display *dp; /* display pointer */
117 extern int Xscreen; /* screen */
118 extern XEvent event; /* event */
119 extern Colormap colormap; /* colormap of display */
120 extern XColor Back_color; /* struct holding background color values */
121 extern WINDOW *last_window_refreshed;
122 /* end of definitions from Xcurse.c */
123
124 extern Window wid;
125 extern XFontStruct *xaefont;
126 XButtonEvent *eventbutton;
127 XMotionEvent *eventmotion;
128 XKeyEvent *eventkey;
129
130 /* ----- radio button declaration section ----- */
131
132 short case_rb_button = 1;
133 char *case_rblabels[] = {
134 "not case sensitive ",
135 "case sensitive "
136 };
137
138 short eight_rb_button = 0;
139 char *eight_rblabels[] = {
140 "don't display eight bit characters",
141 "display eight bit characters"
142 };
143
144 short expand_rb_button = 0;
145 char *expand_rblabels[] = {
146 "do not expand tabs",
147 "expand tabs to spaces"
148 };
149
150 short indent_rb_button = 0;
151 char *indent_rblabels[] = {
152 "do not indent ",
153 "automatically indent "
154 };
155
156 short liter_rb_button = 0;
157 char *liter_rblabels[] = {
158 "metacharacters allowed",
159 "literal search"
160 };
161
162 short over_rb_button = 0;
163 char *over_rblabels[] = {
164 "insert characters ",
165 "replace characters "
166 };
167
168 short stat_rb_button = 0;
169 char *stat_rblabels[] = {
170 "no status line",
171 "display status line"
172 };
173
174 short window_rb_button = 1;
175 char *window_rblabels[] = {
176 "display only one buffer",
177 "display multiple buffers"
178 };
179
180 short wrap_rb_button = 1;
181 char *wrap_rblabels[] = {
182 "cut off line at right margin",
183 "allow line of any length"
184 };
185
186 short forward_rb_button = 0;
187 char *forward_rblabels[] = {
188 "search reverse",
189 "search forward"
190 };
191
192 char *pblabel[] = {
193 "settings OK",
194 "cancel"
195 };
196
197 short srch_fwd_rb_button = 0;
198 char *srch_fwd_rblabels[] = {
199 "search reverse",
200 "search forward"
201 };
202
203 short srch_lit_rb_button = 0;
204 char *srch_lit_rblabels[] = {
205 "allow metacharacters",
206 "literal search"
207 };
208
209 short srch_cas_rb_button = 0;
210 char *srch_cas_rblabels[] = {
211 "not case sensitive search",
212 "case sensitive search"
213 };
214
215 char *srch_pblabel[] = {
216 "settings OK",
217 "cancel"
218 };
219
220
221 char *xsrch_string;
222
223 /* ----- replace panel declarations ----- */
224 short rpl_fwd_rb_button = 0;
225 char *rpl_fwd_rblabels[] = {
226 "search reverse",
227 "search forward"
228 };
229
230 short rpl_lit_rb_button = 0;
231 char *rpl_lit_rblabels[] = {
232 "allow metacharacters",
233 "literal search"
234 };
235
236 short rpl_cas_rb_button = 0;
237 char *rpl_cas_rblabels[] = {
238 "not case sensitive search",
239 "case sensitive search"
240 };
241
242 char *rpl_pblabel[] = {
243 "settings OK",
244 "cancel"
245 };
246
247 char *xold_string;
248 char *xnew_string;
249
250 int tempx, tempy;
251 int wheight, wwidth;
252
253 /* ----- read panel declarations ----- */
254 char *read_pblabel[] = {
255 "OK",
256 "cancel"
257 };
258
259 char *xread_string;
260
261 /* -----write panel declarations ----- */
262 char *write_pblabel[] = {
263 "OK",
264 "cancel"
265 };
266
267 char *xwrite_string;
268
269 /* ----- buffer panel declarations ----- */
270 char *buff_pblabel[] = {
271 "OK",
272 "cancel"
273 };
274
275 char *xbuff_string;
276
277 /* ----- define key panel declarations ----- */
278 char *defkey_pblabel[] = {
279 "OK",
280 "cancel"
281 };
282
283 char *xdefkey_string;
284 int menu_active;
285
286 char *menubackground; /* name of background color */
287 char *menuforeground; /* name of foreground color */
288 int menufore_pixel; /* the pixel value of the foreground color */
289 int menuback_pixel; /* the pixel value of the background color */
290 XColor menuFore_color; /* structure which holds foreground color values */
291 XColor menuBack_color; /* structure which holds background color values */
292
293 static unsigned int xae_window_height, xae_window_width;
294
295 #define icon_width 48
296 #define icon_height 48
297
298 static int xfd;
299 static int number_of_events;
300 static fd_set ttymask;
301 static struct timeval timeout;
302
303 static char xae_in_focus = TRUE;
304
305 void
event_init()306 event_init()
307 {
308 XSelectInput(dp, wid, (KeyPressMask | ButtonPressMask | ButtonReleaseMask |
309 ExposureMask | ButtonMotionMask | PointerMotionMask | StructureNotifyMask |
310 FocusChangeMask));
311 in_char = 0;
312 xae_window_height = LINES * fontheight;
313 xae_window_width = COLS * fontwidth;
314 eventbutton = (XButtonEvent *) &event;
315 eventmotion = (XMotionEvent *) &event;
316 eventkey= (XKeyEvent *) &event;
317 #ifdef hide_cursor
318 ae_cursor = XCreateFontCursor(dp, XC_arrow);
319 XDefineCursor(dp, wid, ae_cursor);
320 cursor_on = TRUE;
321 blank_pix = XCreateBitmapFromData(dp, wid, blank_bits, 1, 1, Back_color, Back_color, XDefaultDepth(dp, Xscreen));
322 blank_cursor = XCreatePixmapCursor(dp, blank_pix, None, 0, 0, 0, 0);
323 #endif
324 panelfont = xaefont;
325 xfd = ConnectionNumber(dp);
326 }
327
328 static void
paste_it()329 paste_it()
330 {
331 int temp_indent; /* if indent must be set FALSE, store original value here */
332 char *temp_buff;
333 char *temp_point;
334 int counter;
335 int buff_counter;
336
337 temp_indent = indent;
338 if (indent)
339 {
340 indent = FALSE;
341 }
342 temp_buff = XFetchBytes(dp, &buff_counter);
343 temp_point = temp_buff;
344 counter = 0;
345 while ((counter < buff_counter) && (temp_buff != NULL))
346 {
347 in = *temp_point;
348 if ((in == '\n') || (in == '\r'))
349 insert_line(TRUE);
350 else
351 insert(in);
352 if (counter < buff_counter)
353 temp_point++;
354 counter++;
355 }
356 indent = temp_indent;
357 if (temp_buff != NULL)
358 free(temp_buff);
359 wmove(curr_buff->win, curr_buff->scr_vert, curr_buff->scr_horz);
360 wrefresh(curr_buff->win);
361 }
362
363 void
event_manage()364 event_manage() /* manage X-windows events for xae */
365 {
366 int valid;
367 int tempy;
368 int tempx;
369 int cut_paste; /* mark text to put in X buffer */
370 int counter;
371 int buff_counter;
372 int temp_indent; /* if indent must be set FALSE, store original value here */
373 char *temp_point;
374 char *temp_buff;
375 int temp;
376
377 valid = FALSE;
378 cut_paste = FALSE;
379
380 do {
381 #ifndef XIF_DEBUG
382 number_of_events = XPending(dp);
383 if ((xae_in_focus) && (number_of_events == 0))
384 {
385 do
386 {
387
388 timeout.tv_sec = 0;
389 timeout.tv_usec = 500000;
390 FD_ZERO(&ttymask);
391 FD_SET(xfd, &ttymask);
392 temp = select((xfd+1), &ttymask, NULL, NULL, &timeout);
393
394 if (temp == 0)
395 {
396 draw_cursor(FALSE);
397 XFlush(dp);
398 }
399 else
400 {
401 draw_cursor(TRUE);
402 XFlush(dp);
403 }
404 } while (temp == 0);
405 }
406 #endif /* ifndef XIF_DEBUG */
407
408 XNextEvent(dp, &event);
409
410
411 if (event.type == KeyPress)
412 {
413 KeySym key;
414 #ifdef hide_cursor
415 if (cursor_on)
416 {
417 XDefineCursor(dp, wid, blank_cursor);
418 XFlush(dp);
419 cursor_on = FALSE;
420 }
421 #endif
422 char text[10];
423 XLookupString(eventkey, text, 10, &key, NULL);
424 char *keystring = XKeysymToString(key);
425
426 if ((keystring != NULL) && (strcmp("Insert", keystring) == 0))
427 {
428 if ((eventkey->state & ShiftMask) != 0)
429 paste_it();
430 else
431 {
432 overstrike = !overstrike;
433 status_display();
434 }
435 }
436 else
437 valid = wgetch(stdscr);
438 }
439 else if ((event.type == MotionNotify) && ((eventmotion->state == (ShiftMask | Button2MotionMask)) || (eventmotion->state == Button1MotionMask)))
440 {
441 #ifdef hide_cursor
442 if (!cursor_on)
443 {
444 cursor_on = TRUE;
445 XDefineCursor(dp, wid, ae_cursor);
446 }
447 #endif
448 tempx = eventbutton->x / fontwidth;
449 tempy = eventbutton->y / fontheight;
450 tempy -= curr_buff->window_top;
451 if (tempy < 0)
452 tempy = 0;
453 if (tempy > curr_buff->last_line)
454 tempy = curr_buff->last_line;
455 if (tempx < 0)
456 tempx = 0;
457 if (tempx > curr_buff->last_col)
458 tempx = curr_buff->last_col;
459 move_to_xy(tempx, tempy);
460 if ((!cut_paste) && (!mark_text))
461 {
462 cut_paste = TRUE;
463 slct(1);
464 }
465 wrefresh(curr_buff->win);
466 }
467 #ifdef hide_cursor
468 else if ((event.type == MotionNotify) && (!cursor_on))
469 {
470 XDefineCursor(dp, wid, ae_cursor);
471 XFlush(dp);
472 cursor_on = TRUE;
473 }
474 #endif
475 else if ((event.type == ButtonRelease) && (((eventbutton->button == Button2) && (eventbutton->button == ShiftMask)) || (eventbutton->button == Button1)) && (cut_paste))
476 {
477 cut_text();
478 cut_paste = FALSE;
479 }
480 else if ((event.type == ButtonPress) && (((eventbutton->button == Button3) && (eventbutton->state == ShiftMask)) || ((eventbutton->button == Button2) && (!(eventbutton->state & ShiftMask)))))
481 {
482 paste_it();
483 }
484 else if ((event.type == ButtonPress) && (eventbutton->button == Button1))
485 {
486 tempy = (eventbutton->y / fontheight);
487 /* make sure cursor is in window */
488 if ((!mark_text) && (tempy < curr_buff->window_top) &&
489 (curr_buff->window_top > 0))
490 {
491 if (!((info_win != 0) &&
492 (tempy < info_win_height)))
493 {
494 while ((tempy < curr_buff->window_top)
495 && (curr_buff->window_top > 0))
496 parse(fn_PB_str); /* prev buffer */
497 }
498 }
499 else if ((!mark_text) && (tempy >
500 (curr_buff->window_top + curr_buff->lines)) &&
501 (curr_buff->next_buff != NULL))
502 {
503 while ((curr_buff->next_buff != NULL) &&
504 (tempy >= curr_buff->next_buff->window_top))
505 parse(fn_NB_str); /* next buffer */
506 }
507 else
508 {
509 tempy -= curr_buff->window_top;
510 tempx = eventbutton->x / fontwidth;
511
512 if (tempy < 0)
513 tempy = 0;
514 if (tempy > curr_buff->last_line)
515 tempy = curr_buff->last_line;
516 if (tempx < 0)
517 tempx = 0;
518 if (tempx > curr_buff->last_col)
519 tempx = curr_buff->last_col;
520 move_to_xy(tempx, tempy);
521 }
522 status_display();
523 wrefresh(curr_buff->win);
524 }
525 else if (event.type == Expose)
526 {
527 while (XCheckTypedEvent(dp, Expose, &event))
528 ;
529 /*
530 | time to cheat, we know which is the last
531 | window that was refreshed
532 */
533
534 clearok(curr_buff->win, TRUE);
535 touchwin(last_window_refreshed);
536 touchwin(last_window_refreshed);
537 wrefresh(last_window_refreshed);
538 XFlush(dp);
539 }
540 else if (event.type == GraphicsExpose)
541 {
542 while (XCheckTypedEvent(dp, GraphicsExpose, &event))
543 ;
544 /*
545 | A real hack to handle situation when
546 | window is partially obscured by another
547 | window. There are better ways to handle
548 | this that completely redrawing the
549 | window.
550 */
551
552 clearok(curr_buff->win, TRUE);
553 touchwin(last_window_refreshed);
554 wrefresh(last_window_refreshed);
555 XFlush(dp);
556 }
557 else if (event.type == ConfigureNotify) /* resize of window */
558 {
559 if ((xae_window_height != event.xconfigure.height ) ||
560 (xae_window_width != event.xconfigure.width ))
561 {
562 LINES = event.xconfigure.height / fontheight;
563 COLS = event.xconfigure.width / fontwidth;
564 XClearWindow(dp, wid);
565 XFlush(dp);
566 reinitscr();
567 resize_check();
568 wrefresh(curr_buff->win);
569 XFlush(dp);
570 xae_window_height = event.xconfigure.height;
571 xae_window_width = event.xconfigure.width;
572 }
573 }
574 else if (event.type == FocusOut) /* loss of focus */
575 {
576 xae_in_focus = FALSE;
577 draw_cursor(TRUE);
578 if (curr_buff->curr_line->changed && curr_buff->journalling)
579 write_journal(curr_buff, curr_buff->curr_line);
580 }
581 else if (event.type == FocusIn) /* acquisition of focus */
582 {
583 xae_in_focus = TRUE;
584 }
585 else if (cut_paste)
586 {
587 cut_text();
588 cut_paste = FALSE;
589 }
590 } while (!valid);
591 }
592
593
594 void
move_to_xy(x,y)595 move_to_xy(x, y) /* move text cursor to mouse cursor position */
596 int x, y; /* horizontal and vertical position of the mouse */
597 {
598 if ((curr_buff->scr_vert > y) || ((curr_buff->scr_vert == y) && (curr_buff->scr_horz > x)))
599 {
600 if ((curr_buff->position != 1) && ((curr_buff->scr_vert - (curr_buff->scr_pos / COLS)) > y))
601 bol(); /* bol */
602 while ((curr_buff->position == 1) && (curr_buff->curr_line->prev_line != NULL) &&
603 ((curr_buff->scr_vert - curr_buff->curr_line->prev_line->vert_len) > y))
604 bol(); /* bol */
605 if ((curr_buff->position == 1) && ((curr_buff->scr_vert -
606 curr_buff->curr_line->prev_line->vert_len) <= y) && (curr_buff->scr_vert > y))
607 eopl(); /* end of prev line */
608 while ((curr_buff->scr_vert != y) && (curr_buff->position > 1))
609 left(TRUE); /* left */
610 while ((curr_buff->scr_vert == y) && (curr_buff->scr_horz > x) && (curr_buff->position > 1))
611 left(TRUE); /* left */
612 if (curr_buff->scr_vert < y)
613 adv_line(); /* adv line */
614 }
615 else
616 {
617 if (((curr_buff->curr_line->vert_len - (curr_buff->scr_pos / COLS)) + curr_buff->scr_vert) <= y)
618 adv_line(); /* adv line */
619 while (((curr_buff->scr_vert + curr_buff->curr_line->vert_len) <= y) &&
620 (curr_buff->curr_line->next_line != NULL))
621 adv_line(); /* adv line */
622 while ((curr_buff->scr_vert < y) && (curr_buff->position < curr_buff->curr_line->line_length))
623 right(TRUE); /* right */
624 while ((curr_buff->scr_horz < x) && (curr_buff->scr_vert == y) &&
625 (curr_buff->position < curr_buff->curr_line->line_length))
626 right(TRUE); /* right */
627 if (curr_buff->scr_vert > y)
628 left(TRUE);
629 }
630 }
631
632 void
eopl()633 eopl() /* move to end of previous line without shifting screen */
634 {
635 if (curr_buff->position != 1)
636 bol();
637 if ((curr_buff->curr_line->prev_line != NULL) && (curr_buff->scr_vert - curr_buff->curr_line->prev_line->vert_len) < 0)
638 {
639 curr_buff->curr_line = curr_buff->curr_line->prev_line;
640 curr_buff->pointer = curr_buff->curr_line->line;
641 curr_buff->position = 1;
642 curr_buff->scr_pos = 0;
643 curr_buff->scr_vert -= curr_buff->curr_line->vert_len;
644 while (curr_buff->position < curr_buff->curr_line->line_length)
645 {
646 curr_buff->pointer++;
647 curr_buff->position++;
648 }
649 curr_buff->scr_pos = scanline(curr_buff->curr_line, curr_buff->position);
650 curr_buff->abs_pos = curr_buff->scr_pos;
651 curr_buff->scr_vert += curr_buff->scr_pos / COLS;
652 curr_buff->scr_horz = curr_buff->scr_pos % COLS;
653 if (mark_text)
654 slct_line("u");
655 }
656 else
657 left(TRUE);
658 }
659
660 void
cut_text()661 cut_text()
662 {
663 int counter;
664 int buff_counter;
665 char *out_buff;
666 char *temp_point;
667 char *temp_buff;
668 struct text *temp_paste;
669 struct text *temp_text;
670
671 temp_paste = paste_buff;
672 paste_buff = NULL;
673 copy();
674 temp_text = paste_buff;
675 counter = 0;
676 while (temp_text != NULL)
677 {
678 counter += temp_text->line_length;
679 temp_text = temp_text->next_line;
680 }
681 out_buff = malloc(counter + 1);
682 temp_point = out_buff;
683 temp_text = paste_buff;
684 while (temp_text != NULL)
685 {
686 buff_counter = 1;
687 temp_buff = temp_text->line;
688 while (buff_counter < temp_text->line_length)
689 {
690 *temp_point = *temp_buff;
691 temp_point++;
692 temp_buff++;
693 buff_counter++;
694 }
695 if (temp_text->next_line != NULL)
696 {
697 *temp_point = '\n';
698 temp_point++;
699 temp_text = temp_text->next_line;
700 free(temp_text->prev_line->line);
701 free(temp_text->prev_line);
702 }
703 else
704 {
705 counter -= 1;
706 *temp_point = '\0';
707 free(temp_text->line);
708 free(temp_text);
709 temp_text = NULL;
710 }
711 }
712 if (counter > 0)
713 XStoreBytes(dp, out_buff, counter);
714 free(out_buff);
715 paste_buff = temp_paste;
716 midscreen(curr_buff->scr_vert, curr_buff->position);
717 wrefresh(curr_buff->win);
718 }
719
720
721 void
raise_window()722 raise_window()
723 {
724 XRaiseWindow(dp, wid);
725 }
726
727 void
set_window_name(name)728 set_window_name(name)
729 char *name;
730 {
731 static char *window_name = NULL;
732
733 if (window_name != NULL)
734 free(window_name);
735
736 window_name = xalloc(strlen("xae:") + strlen(name) + 1);
737 strcpy(window_name, "xae:");
738 strcat(window_name, name);
739 XStoreName(dp, wid, window_name);
740 XSetIconName(dp, wid, window_name);
741 }
742