update experimental gcc 6 patch to gcc 6.1.0 release
[AROS.git] / workbench / tools / Edit / Events.c
blob1a33417881f6a7114f3c70db21d604eea5b25de6
1 /**********************************************************
2 ** Events.c : Process events coming from main window and **
3 ** public port. Written by T.Pierron and C.Guillaume. **
4 ** Free software under terms of GNU license. 12 nov 2000 **
5 **********************************************************/
7 #include <intuition/intuition.h> /* Std types */
8 #include <devices/inputevent.h> /* For raw keymap conversion */
9 #include <dos/dos.h>
10 #include "Jed.h"
11 #include "Utility.h"
12 #include "Events.h"
13 #include "IPC_Prefs.h"
14 #include "DiskIO.h"
15 #include "Macros.h"
16 #include "Gui.h"
17 #include "Edit.h"
18 #include "Search.h"
19 #include "ProtoTypes.h"
21 #define CATCOMP_NUMBERS /* String ID for ErrMsg() */
22 #include "strings.h"
24 static struct InputEvent ie = {0,IECLASS_RAWKEY}; /* Keyboard translation map */
25 extern struct IntuiMessage msgbuf;
26 extern Project edit;
28 UBYTE record = 0;
30 /*** Process keyboard events ***/
31 void handle_kbd(Project p)
33 static UBYTE buffer[8], shift;
35 /* Look is rawkey can be processed, thus doesn't translate it */
36 if(msgbuf.Code > 0x7E) { record |= 0x80; return; }
38 /* Look if keypad should be processed as a PC one */
39 if( (*buffer = (msgbuf.Qualifier & IEQUALIFIER_NUMERICPAD && msgbuf.Code >= N0_KEY &&
40 msgbuf.Code <= N9_KEY && (prefs.xtend || msgbuf.Qualifier & CTRLKEYS)))
41 && !prefs.xtend )
42 /* Clear CONTROL qualifier, if no PC keypad emulation */
43 msgbuf.Qualifier &= ~CTRLKEYS;
45 shift = (msgbuf.Qualifier & SHIFTKEYS ? 1 : 0);
47 switch( msgbuf.Code )
49 case N0_KEY:
50 if( *buffer ) {
51 /* Switch with replacement cursor */
52 p->cursmode = !p->cursmode;
53 inv_curs(p, FALSE); inv_curs(p, TRUE);
54 return;
55 } break;
56 case N1_KEY: if( *buffer ) { horiz_pos(p,MAXPOS); return; } break;
57 case N3_KEY: if( *buffer ) { pg_updown(p, 1); return; } break;
58 case N7_KEY: if( *buffer ) { horiz_pos(p, 0); return; } break;
59 case N9_KEY: if( *buffer ) { pg_updown(p,-1); return; } break;
60 case SPACE_KEY:
61 /* Amiga space indent line */
62 if( msgbuf.Qualifier & AMIGAKEYS ) {
63 indent_by(p, ' ', shift ? -1:1); return;
64 } break;
65 case TAB_KEY:
66 if( msgbuf.Qualifier & AMIGAKEYS ) {
67 indent_by(p, '\t',shift ? -1:1); return;
68 } break;
69 case BS_KEY:
70 if( p->ccp.select )
71 del_block( p );
72 else if( msgbuf.Qualifier & AMIGAKEYS )
73 amiga_k(p);
74 else if( shift )
75 cut_line(p,0);
76 else
77 back_space(p, (msgbuf.Qualifier & ALTKEYS) != 0);
78 return;
79 case ESC_KEY:
80 /* Pressing ESC key while text is selected, unmark all **
81 ** otherwise we want to add the escape character */
82 if(p->ccp.select==0) break;
83 unmark_all(p,TRUE); return;
84 case NPERIOD_KEY: if( *buffer == 0 ) break;
85 case DEL_KEY:
86 if( p->ccp.select )
87 del_block( p );
88 else if( shift )
89 cut_line(p,1);
90 else
91 del(p, (msgbuf.Qualifier & ALTKEYS) != 0);
92 return;
93 case N8_KEY: if( *buffer == 0 ) break;
94 case UP_KEY:
95 if( msgbuf.Qualifier & CTRLKEYS )
96 move_to_line(p,0,LINE_AS_IS);
97 else if( shift )
98 if( msgbuf.Qualifier & ALTKEYS )
99 scroll_ydelta(p,-1);
100 else
101 jump_vert(p,-1);
102 else
103 curs_up(p);
104 return;
105 case N2_KEY: if( *buffer == 0 ) break;
106 case DOWN_KEY:
107 if( msgbuf.Qualifier & CTRLKEYS )
108 move_to_line(p,p->max_lines-1,LINE_AS_IS);
109 else if( shift )
110 if( msgbuf.Qualifier & ALTKEYS )
111 scroll_ydelta(p, 1);
112 else
113 jump_vert(p, 1);
114 else
115 curs_down(p);
116 return;
117 case N6_KEY: if( *buffer == 0 ) break;
118 case RIGHT_KEY: /* Used for various things! */
119 if( msgbuf.Qualifier & CTRLKEYS )
120 if( shift )
121 edit = select_panel(edit, NEXT_PROJECT);
122 else
123 horiz_pos(p,MAXPOS);
124 else if( shift )
125 if( msgbuf.Qualifier & ALTKEYS )
126 scroll_xdelta(p, gui.xstep);
127 else
128 jump_horiz(p, 1);
129 else
130 curs_right(p, (msgbuf.Qualifier & ALTKEYS) != 0);
131 return;
132 case N4_KEY: if( *buffer == 0 ) break;
133 case LEFT_KEY:
134 if( msgbuf.Qualifier & CTRLKEYS )
135 if( shift )
136 edit = select_panel(edit, PREV_PROJECT);
137 else
138 horiz_pos(p,0);
139 else if( shift )
140 if( msgbuf.Qualifier & ALTKEYS )
141 scroll_xdelta(p, -gui.xstep);
142 else
143 jump_horiz(p,-1);
144 else
145 curs_left(p, (msgbuf.Qualifier & ALTKEYS) != 0);
146 return;
147 case RETURN_KEY:
148 case NENTER_KEY:
149 if( msgbuf.Qualifier & CTRLKEYS )
151 STRPTR path = GetIncludeFile(p, p->edited);
152 Project new = NULL;
154 if(NULL != path && (shift == 0 || warn_modif(edit)))
155 new = load_and_activate(edit, path, shift);
156 if(NULL != new)
157 edit = new;
159 else
160 split_curline( p );
161 return;
162 #ifdef __AROS__
163 case PGDOWN_KEY: pg_updown(p, 1); return;
164 case PGUP_KEY: pg_updown(p, -1); return;
166 case HOME_KEY:
167 if( msgbuf.Qualifier & CTRLKEYS ) move_to_line(p,0,LINE_AS_IS);
168 else horiz_pos(p,0);
169 return;
170 case END_KEY:
171 if( msgbuf.Qualifier & CTRLKEYS ) move_to_line(p,p->max_lines-1,LINE_AS_IS);
172 else horiz_pos(p,MAXPOS);
173 return;
175 case RAWKEY_NM_WHEEL_UP:
176 scroll_ydelta(p, -3);
177 return;
179 case RAWKEY_NM_WHEEL_DOWN:
180 scroll_ydelta(p, 3);
181 return;
182 #endif
184 #if DEBUG
185 case F1_KEY:
186 printf("mask = 0x%02x\n", RP->Mask); return;
187 case F2_KEY:
188 show_modifs(&p->undo); return;
189 case F3_KEY:
190 show_modifs(&p->redo); return;
191 #endif
194 /* Translate key (with dead one) using keymap library */
195 ie.ie_Code = msgbuf.Code;
196 ie.ie_EventAddress = *((APTR *)msgbuf.IAddress);
198 /* Look if CTRL qualifier is used */
199 if( msgbuf.Qualifier & (CTRLKEYS|AMIGAKEYS) )
201 /* Discard qualifiers, if CTRL+<a-z> is pressed a control char will **
202 ** be returned, which does not reflect the key we want to process. */
203 ie.ie_Qualifier = msgbuf.Qualifier & ~(CTRLKEYS | AMIGAKEYS | IEQUALIFIER_CAPSLOCK);
205 /* If it's not a known shortcut, insert control char instead */
206 if(MapRawKey(&ie, buffer, 8, NULL) > 0)
208 if( msgbuf.Qualifier & AMIGAKEYS )
210 /* This is too annoying to insert into menus: Amiga+2~9 enable **
211 ** to quickly change tabstop of current project (not in prefs) */
212 if( '2' <= *buffer && *buffer <= '9' )
214 WORD tabstop = *buffer - '0';
215 if(tabstop != p->tabsize)
216 p->tabsize = tabstop, inv_curs(p, FALSE),
217 active_project(p, FALSE);
218 return;
221 /* CTRL + `1' ~ `0' => activate project nb. x */
222 else if( '0' <= *buffer && *buffer <= '9' )
224 edit = select_panel(edit,*buffer == '0' ? -10 : '0' - *buffer);
225 return;
227 else switch(*buffer)
229 case '\\':change_case(p, 0); return;
230 case '/': change_case(p, 1); return;
231 case 'j': join_strip(p); return;
232 case 'n': FindPattern(p, 1); return;
233 case 'p': FindPattern(p,-1); return;
234 case 'q': handle_menu(111); return;
235 case 'Q': handle_menu(113); return;
236 case 'r': ReplacePattern(p); return;
237 case 'R': ReplaceAllPat(p); return;
238 case 's': FindWord(p, 1); return;
239 case 'S': FindWord(p,-1); return;
240 case 'z': last_modif(&p->undo, 0); return;
241 case '[': handle_menu(401); return;
242 case ']': handle_menu(402); return;
247 /* Make sure this time qualifiers are taken into account */
248 ie.ie_Qualifier = msgbuf.Qualifier;
250 /* Map RAWKEY to ANSI (dead keys return 0) */
251 if(MapRawKey(&ie, buffer, 8, NULL) > 0)
253 /* register UBYTE code = *buffer; */
255 /* Inserting one char is the most common operation **
256 ** and therefore needs to be highly optimized: */
257 if( add_char(&p->undo, p->edited, p->nbc, *buffer) )
259 REDRAW_CURLINE(p);
260 curs_right(p, FALSE);
261 } else ThrowError(Wnd, ErrMsg(ERR_NOMEM));
263 if(record) reg_act_addchar( *buffer ), record |= 0x80;
267 /*** Handle menu related events ***/
268 void handle_menu( LONG MenuID )
270 static UBYTE shift;
272 shift = (msgbuf.Qualifier & SHIFTKEYS ? 1 : 0);
274 switch( MenuID )
276 case 101: /* New file */
277 { Project new;
278 BusyWindow(Wnd);
279 if( ( new = new_project(edit, &prefs) ) )
281 /* Compute panel tabs size */
282 inv_curs(edit, FALSE);
283 reshape_panel(new);
284 active_project(edit=new, TRUE);
286 } else ThrowError(Wnd, ErrMsg(ERR_NOMEM));
287 WakeUp(Wnd);
288 } break;
289 case 102: /* Split open */
290 { STRPTR path;
291 /* Ask a new file name, using the same working directory as current document */
292 if(NULL != (path = ask_load(Wnd, (AskArgs *)&edit->path, FALSE, GetMenuText(102))))
294 Project new;
295 /* Use current project if it is empty and unmodified */
296 if( (new = load_and_activate(edit, path, (edit->path == NULL && (edit->state & MODIFIED) == 0) ? 2 : 3) ) )
297 edit = new;
299 } break;
300 case 103: /* Open (in current panel) */
301 if( warn_modif(edit) )
303 if( shift == 0 )
305 STRPTR path;
306 if(NULL != (path = ask_load(Wnd, (AskArgs *)&edit->path, TRUE, GetMenuText(103))))
307 load_and_activate(edit, path, 1);
309 else reload_project( edit );
310 } break;
311 case 105: /* Save */
312 if(0 == shift) goto case_sav;
314 case 106: save_project (edit,TRUE,TRUE); break; /* Save as */
315 case_sav: save_project (edit,TRUE,FALSE); break; /* Save one file */
316 case 107: save_projects(edit,FALSE); break; /* Save changes */
317 case 108: print_project (edit); break; /* Print project */
318 case 109: show_info(edit); break; /* Information */
320 case 113: /* Save if necessary, then quit */
321 if((edit->state & MODIFIED) && save_project(edit, TRUE, FALSE) == 0)
322 break;
323 case 111: /* Close project */
324 { Project new = edit->prev;
325 if(new == NULL) new = edit->next;
326 /* Check if there were modifications */
327 if( close_project(edit) )
329 /* If there is another opened project, shows it */
330 inv_curs(edit,FALSE); FreeVec(edit);
331 if( new != NULL )
332 reshape_panel(new),
333 active_project(edit = new, FALSE);
334 else
335 /* Otherwise quits */
336 cleanup(0,0);
338 } break;
339 case 112: /* Quit */
340 /* Modified project not yet saved */
341 inv_curs(edit, FALSE);
342 if(NULL != (edit = (shift ? save_projects(edit, TRUE) : close_projects())))
343 reshape_panel(edit),
344 active_project(edit, FALSE);
345 else
346 cleanup(0,0);
347 break;
348 case 201: /* Cut */
349 case 202: /* Copy to clipboard */
350 if( edit->ccp.select == 0 ) break;
352 if( CBWriteFTXT(edit->ccp.yc > edit->ccp.yp ? edit->ccp.line : edit->ccp.cline, &edit->ccp) ) {
353 if( MenuID == 202 ) unmark_all(edit,TRUE);
354 else del_block( edit );
356 break;
357 case 203: /* Paste from clipboard */
358 { LONG buf[3];
359 /* Read chars */
360 if( !CBReadCHRS(&edit->undo, edit->edited, edit->nbc, buf) )
361 /* CBReadCHRS will show the right error */
362 break;
364 /* Just one line concerned? */
365 edit->max_lines += buf[2];
366 if( buf[1] == 0 ) REDRAW_CURLINE(edit)
368 /* Move cursor to the end of pasted text? */
369 if( shift == 0 ) move_cursor(edit,buf[0],buf[1]);
370 if( buf[1]>0 ) redraw_content(edit,edit->show,gui.topcurs,gui.nbline);
371 if( edit->ccp.select ) move_selection(edit, edit->nbrc, edit->nbl);
372 inv_curs(edit,TRUE); prop_adj(edit);
373 } break;
374 case 204: /* Mark text */
375 if(shift) MenuID=205;
376 case 205: /* Mark columnar */
377 move_selection = SwitchSelect(edit,MenuID-204,0);
378 break;
379 case 206: mark_all(edit); break; /* Select all */
380 case 207: amiga_k(edit); break; /* Del line */
381 case 2071: indent_by(edit,'\t', 1); break; /* Indent */
382 case 2072: indent_by(edit,'\t',-1); break; /* Unindent */
383 case 2073: change_case(edit,0); break; /* Upper */
384 case 2074: change_case(edit,1); break; /* Lower */
385 case 2075: change_case(edit,2); break; /* Toggle */
386 case 208: insert_file(edit); break; /* Insert file */
387 case 209:
388 if(shift == 0) {
389 rollback(&edit->undo); break; /* Undo */
391 case 210: rollback(&edit->redo); break; /* Redo */
392 case 301: setup_winsearch(edit,0); break; /* Search */
393 case 302: setup_winsearch(edit,1); break; /* Replace */
394 case 3031: FindPattern(edit, 1); break; /* Find next */
395 case 3032: FindPattern(edit,-1); break; /* Find prev */
396 case 3033: ReplacePattern(edit); break; /* Replace next */
397 case 304: pg_updown(edit,-1); break; /* PgUp */
398 case 305: pg_updown(edit, 1); break; /* PgDown */
399 case 306: goto_line(edit); break; /* Goto line */
400 case 307: match_bracket(edit); break; /* Match bracket */
401 case 308: last_modif(&edit->undo,0); break; /* Last modif */
402 case 309: horiz_pos(edit,0); break; /* Home */
403 case 310: horiz_pos(edit,MAXPOS); break; /* End */
404 case 401: start_macro(); break; /* Record */
405 case 402: stop_macro(); break; /* Stop recording */
406 case 403:
407 if(shift == 0) { play_macro(1); break; } /* Play current macro */
408 case 404: repeat_macro(edit); break; /* Repeat one or more times */
409 case 501: ask_new_screen(); break; /* Change screen mode */
410 case 502: ask_new_font(); break; /* Change text font */
411 case 503: setup_winpref(); break; /* General prefs */
412 case 505: save_prefs(&prefs); break; /* Save prefs */
414 case 504: ask_prefs(edit,0,GetMenuText(504)); break; /* Load prefs */
415 case 506: ask_prefs(edit,1,GetMenuText(506)); break; /* Save prefs as */
420 /** Public port of Jano **/
421 static struct MsgPort *port = NULL, *reply;
422 static struct JPacket *cmd = NULL;
424 UBYTE *PortName = JANO_PORT;
426 /** Look if jano is already running **/
427 char find_janoed( StartUpArgs *args )
429 ULONG sigwait;
430 if( (reply = (struct MsgPort *) FindPort(PortName)) )
432 PortName = NULL; /* Private port */
433 if( ( sigwait = create_port() ) )
435 /* Send to JanoEditor that someone tries to start it again */
436 cmd->class = CMD_NEWEDIT;
437 cmd->msg.args = args;
438 PutMsg(reply, (struct Message *)cmd);
439 /* cmd packet is associated with "port", thus reply will be done here */
440 Wait( sigwait | SIGBREAKF_CTRL_C );
441 /* Unqueue message */
442 GetMsg( port );
444 /* Cleanup will be done later */
445 return 1;
446 } else return 0;
449 /** Setup public port of the editor **/
450 ULONG create_port( void )
452 /* Create a port and */
453 if( ( port = (struct MsgPort *) CreateMsgPort() ) )
455 /* Set this port public */
456 port->mp_Node.ln_Name = PortName;
457 port->mp_Node.ln_Pri = 0;
458 AddPort( port );
460 /* Create a message that can be sent to the editor */
461 if( ( cmd = (struct JPacket *) CreateIORequest(port, (long) sizeof (*cmd)) ) )
462 return (ULONG)(1 << port->mp_SigBit);
464 DeletePort(port);
466 return 0;
469 /** Send a command to preference tool **/
470 char send_pref(PREFS *prefs, ULONG class)
472 /* The port can be shutted down at any time! */
473 if( ( reply = (struct MsgPort *) FindPort(JANOPREFS_PORT)) )
475 cmd->class = class;
476 CopyMem(prefs, &cmd->msg.prefs, sizeof(*prefs));
478 PutMsg(reply, (struct Message *)cmd);
479 Wait( 1 << port->mp_SigBit | SIGBREAKF_CTRL_C );
480 GetMsg( port );
481 return 1;
482 } else return 0;
485 /** Shutdown port **/
486 void close_port( void )
488 if( cmd ) DeleteExtIO((struct IORequest *)cmd);
489 if( port ) RemPort(port), DeleteMsgPort(port);
492 /*** Handle messages posted to public port of Jano ***/
493 void handle_port( void )
495 struct JPacket *msg; char update = 0;
496 extern PREFS tmpprefs;
497 while( ( msg = (struct JPacket *) GetMsg(port) ) )
499 switch( msg->class )
501 case CMD_NEWEDIT:
502 /* Look if there are projects to load */
503 if(msg->msg.args->sa_NbArgs > 0)
505 inv_curs(edit, FALSE);
506 edit = create_projects(edit, msg->msg.args->sa_ArgLst, msg->msg.args->sa_NbArgs);
507 reshape_panel(edit);
508 active_project(edit,TRUE);
509 clear_brcorner();
511 case CMD_SHOW:
512 WindowToFront( Wnd );
513 ScreenToFront( Scr );
514 ActivateWindow( Wnd );
515 break;
516 case CMD_KILL: cleanup(0,0); break;
517 case CMD_PREF:
518 /* Send a copy of preference struct */
519 prefs.current = Scr;
520 CopyMem(&prefs, &msg->msg.prefs, sizeof(prefs));
521 break;
522 case CMD_SAVPREF: update = 2; goto save;
523 case CMD_NEWPREF: update = 1;
524 /* Preference tool has sent a new config! */
525 save: CopyMem(&msg->msg.prefs, &tmpprefs, sizeof(tmpprefs)); break;
527 ReplyMsg((struct Message *)msg);
529 /* Preferences have changed? */
530 if(update == 2) save_prefs(&tmpprefs);
531 if(update >= 1) update_prefs(edit);