1 
2 /*
3 	emx (small EMacs clone for X)
4 	(C) 2002, Jean-Pierre Demailly
5 	released in the public domain
6 
7 	derived from edx ver. 0.56, (C) 2002, Terry Loveall
8 	Based upon the original work ee.c of Yijun Ding, (C) 1991 which is
9 	in the public domain.
10 
11 	This program comes with no warranties. Use at your own risk.
12 */
13 
14 #define EDIT "emx"
15 
16 #ifndef MINIMAL
17 #define DEFAULT_RC "emxrc"
18 #endif
19 
20 /* Help screen -- rewrite to suit your own tastes */
21 
22 /* include the editor engine */
23 #include "edit.c"
24 
25 /* All this stuff consists of the emacs-like bindings */
26 
27 #ifdef GREEK
ctrlc_key(int key)28 void ctrlc_key(int key)
29 {
30 	key_greek(key);
31 	doCtrlC = var_greek;
32 }
33 #endif
34 
35 #ifdef MINIMAL
key_binding(int key)36 void key_binding(int key)
37 {
38 	switch(key) {
39 		case 'c': SYSTEM("xcalc"); break;				/* Alt-C xcalc*/
40 		case 'd': new_edit("/c/text/phone.dir"); break;	/* Alt-D phone Dir */
41 		case 'l': SYSTEM("xcalendar"); break;			/* Alt-L xcalendar */
42 		case 'u': redo(); break;						/* Alt-U redo */
43 	}
44 }
45 #endif
46 
47 /* ctrl X keys */
ctrlx_key(int key)48 void ctrlx_key(int key)
49 {
50 	switch(key | 0x60) {
51 		case 'c': sys_exit(0); break;		/* ^XC exit only if file saved */
52 		case 'd': key_delword(0); break;	/* ^XD delete word */
53 		case 'f': file_save(0,1); break;	/* ^XF open new file */
54 		case 'h': show_help(0); break;		/* ^XH show help menu */
55 		case 'i': block_read(); break;		/* ^XI read file into cursor pos */
56 		case 'k': block_line(); break;		/* ^XK delete line */
57 		case 'm': key_macros(1); break; 	/* ^XM record macro */
58 		case 'p': key_macros(0); break; 	/* ^XP play macro */
59 		case 'q': sys_exit(2); break;		/* ^XQ exit even if file unsaved */
60 		case 's': do_save(); break; 		/* ^XS write block to disk */
61 		case 't': tab_size(); break;		/* ^XT get tab size */
62 		case 'v': block_write(); break; 	/* ^XV write block to disk */
63 		case 'w': file_save(0,-1); break;	/* ^XW save file as */
64 		case 'x': goto_last(); break;		/* ^XX goto last pos */
65 	}
66 	doCtrlX = 0;
67 	show_top();
68 }
69 
70 /* Shift, control and bare Function keys */
key_func(int key)71 void key_func(int key)
72 {
73 	if(keve->state & ShiftMask)
74 		switch(key) {
75 		case XK_Insert	: do_paste(); return; 			/* Shift Ins paste */
76 		case XK_Delete	: do_select(1); return;			/* Shift Del cut */
77 		}
78 	if((keve->state & ShiftMask) && !flag[BLK] &&
79 		key >= XK_Home && key <= XK_End) block_mark();	/* enable marked block with Shift */
80 	if(keve->state & ControlMask) {
81 		switch(key) {
82 		case XK_Tab		: word_mark(); break;			/* ^Tab mark cursor word */
83 #ifndef MINIMAL
84 		case XK_F1		: new_edit(DOCDIR"/MANUAL.emx"); break;			/* ^F1 open emx Manual */
85 #endif
86 		case XK_F9		: new_edit(""); break;			/* ^F3 open new emx */
87 		case XK_Home	: top(); break; 				/* ^Home bof */
88 		case XK_End 	: goto_y(ytot); break;			/* ^End eof */
89 		case XK_Left	: word_left(); break;			/* ^Left word left */
90 		case XK_Right	: word_right(); break;			/* ^Right word right */
91 		case XK_Insert	: do_select(0); break;			/* ^Ins copy */
92 		}
93 	} else
94 		switch(key) {
95 		case XK_F1		: show_help(0); break;			/* F1 show help */
96 		case XK_F2		: do_save(); break; 			/* F2 save file and resume */
97 		case XK_F3		: file_save(0,1); break;		/* F3 open new file */
98 		case XK_F4		: find_match(); break; 			/* F4 find {} () [] match  */
99 		case XK_F5		: run(); break; 				/* F5 get and run cmd */
100 		case XK_F6		: chgdir(); break; 				/* F6 get & change to dir */
101 		case XK_F7		: block_mark(); break;			/* F7 set mark block on */
102 		case XK_F8		: block_mark(); break;			/* F8 set mark block on */
103 #ifndef MINIMAL
104 		case XK_F9		: req_edit(); break;		/* F9 open new file in new window */
105 #endif
106 		case XK_F10 	: key_binding('z'); break;				/* F10 open rxvt in cur.dir */
107 		case XK_F12 	: show_flag(OVR, !flag[OVR]); break;/* Ins toggle insert mode */
108 		case XK_Return	: key_return(); break;			/* Enter newline at cursor */
109 		case XK_Tab 	: key_tab(0); break;			/* Tab insert tab char at cursor */
110 		case XK_BackSpace: key_backspace(); break;		/* BS delete prev char */
111 		case XK_Insert	: show_flag(OVR, !flag[OVR]); break;/* Ins toggle insert mode */
112 		case XK_Delete	: key_delete(); break;			/* Del delete cursor char */
113 		case XK_Page_Up : cursor_pageup(); break;		/* PgUp */
114 		case XK_Page_Down: cursor_pagedown(); break;	/* PgDn */
115 		case XK_End 	: goto_x(strlen(line_start+1)+1); break;/* End eol */
116 		case XK_Home	: goto_x(1); break; 			/* Home bol */
117 		case XK_Up	: cursor_up(); break;			/* up */
118 		case XK_Down	: cursor_down(); break; 		/* down */
119 		case XK_Right	: cursor_right(); break;		/* right */
120 		case XK_Left	: cursor_left(); break; 		/* left */
121 	}
122 	if(!(keve->state & ShiftMask) && flag[BLK]) mark_off();	 // turn off marked block
123 }
124 
125 /* Control keys */
key_control(int key)126 void key_control(int key)
127 {
128 	if(!(keve->state & ShiftMask) && flag[BLK]) mark_off();
129 	switch(key|0x60) {
130 		case 'a': goto_x(1); break; 		/* bol */
131 		case 'b': cursor_left(); break; 	/* left */
132 #ifdef GREEK
133 		case 'c': doCtrlC = 1; break; 		/* ^C switch */
134 #endif
135 		case 'd': key_delete(); break;		/* delete cursor char */
136 		case 'e': goto_x(strlen(line_start+1)+1); break;	/* goto eol */
137 		case 'f': cursor_right(); break;	/* right */
138 		case 'h': key_backspace(); break;	/* destructive backspace */
139 		case 'j': key_return(); break;		/* newline at cursor */
140 		case 'k': key_delword(1); break;	/* delete to eol */
141 		case 'l': expose=1; scr_update(); expose=0; break;		/* refresh screen */
142 		case 'n': cursor_down(); break; 	/* down */
143 		case 'o': show_mode(); break; 		/* change modes */
144 		case 'p': cursor_up(); break;		/* up */
145 		case 'q': literal = 1; break;		/* literal */
146 		case 'r': goto_search(1); break;	/* ^R find backward */
147 		case 's': goto_search(0); break;	/* ^S find foreword */
148 		case 't': transpose(); break;		/* ^T transpose */
149 		case 'u': if (search_mode<=1)		/* repeat search */
150 				goto_find(cur_pos, search_mode);
151 			  else				/* repeat replace */
152 				ask_replace();
153 			  break; /* search or replace again */
154 		case 'v': cursor_pagedown(); break; 	/* ^V pgdn */
155 		case 'w': reset_mark();
156                           block_copy(1); break; 	/* ^W cut block at buffer */
157 		case 'x': doCtrlX = 1; break;		/* ^X switch */
158 		case 'y': block_paste(); break; 	/* ^Y copy buffer at cursor */
159 		case 'z': iconify(); break;		/* ^Z iconify window */
160 		case 0x7f: undo(0); break;		/* ^_ undo */
161 							/* user typed Ctrl-_ */
162 	}
163 	show_top();
164 }
165 
166 /* Escape keys */
key_escape(int key)167 void key_escape(int key)
168 {
169 	switch(tolower(key)) {
170 		case ' ':
171 		case '.': block_mark(); break;		/* Esc-BLANK set mark block on */
172 #ifndef MINIMAL
173 		case '!': doEscap = 2; show_note(ALT_KEY_BINDINGS); return;	/* Esc-! = Alt-key bindings */
174 #endif
175 		case '_': redo(); break;		/* Esc-_ redo */
176 		case '%': goto_replace(); break;	/* Esc-% replace */
177 
178 		case '<': top(); break;			/* Esc-< bof */
179 		case '>': y = screen_height-1; goto_ptr(file_end); break; 	/* Esc-> eof */
180 		case 'b': word_left(); break;		/* Esc-B word left */
181 		case 'f': word_right(); break;		/* Esc-F word right */
182 		case 'g': keve->state & ControlMask ?
183 					goto_line() :	/* goto line# */
184 					key_return(); break;	/* newline */
185 #ifdef JUSTIFY
186 		case 'j': block_format(1); break;	/* Esc-J reformat & fill block */
187 #endif
188 		case 'l': chg_case(0); break; 		/* Esc-L lower case block */
189 		case 'm': window_size(); break; 	/* Esc-M get right margin */
190                 case 'n': scroll_up(); break;		/* Esc-N scroll down (!) */
191 		case 'p': scroll_down(); break;		/* Esc-P scroll up (!) */
192 		case 'q': block_format(0); break;	/* Esc-Q reformat block */
193 		case 'u': chg_case(1); break; 		/* Esc-U upper case block */
194 		case 'v': cursor_pageup(); break;	/* Esc-V pgup */
195 
196 		case 'w': reset_mark(); block_copy(0);
197                           reset_mark(); break; 		/* Esc-W copy block to buffer */
198 		case 'x': switch_marks(); break;	/* Esc-X switch between block marks */
199 	}
200 	doEscap = 0;
201 	show_top();
202 }
203 
204 /* single char interpreter */
main_exec(int key)205 void main_exec(int key)
206 {
207 	cur_pos = get_cur();
208 	if (update_scr) {
209 		undraw_cursor();
210 		if(flag[REC]) rec_macro(key);
211 	}
212 	if (help_done){
213 		help_done = 0;
214 		flag[SHW] = 1;
215 	} else if (literal) {
216 		key_normal(keve->state & ControlMask ? key & 0x1f : key);
217 		literal = 0;
218 	} else {
219 		if (key==XK_Escape) doEscap = 1; else
220 		if (key & 0xFF00) key_func(key); else
221 		if (doEscap==2 || (keve->state & Mod1Mask)) key_binding(key);
222 		else {
223 			if (doEscap==1) key_escape(key); else
224 #ifdef GREEK
225 			if (doCtrlC) ctrlc_key(key); else
226 #endif
227 			if (doCtrlX) ctrlx_key(key); else
228 			{
229 				if (keve->state & ControlMask) key &= 0x1f;
230 				if (key >= BLNK)  {
231 					flag[BLK] = 0;
232 					key_normal(key);
233 				}
234 				else key_control(key);
235 			}
236 		}
237 	}
238 	if(!doCtrlX && old_pos != line_start) {
239 		last_pos = old_pos;
240 		old_pos = line_start;
241 	}
242 	cur_pos = get_cur();
243 
244 	if(update_scr) scr_update();
245 }
246 
247