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