Don't keep asking for S2EVENT_CONNECT reports if driver doen't
[AROS.git] / workbench / tools / Edit / Events.c
blob088247fbf3e67814df06fb976d1e87a371b4e015
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 split_curline( p ); return;
160 #ifdef __AROS__
161 case PGDOWN_KEY: pg_updown(p, 1); return;
162 case PGUP_KEY: pg_updown(p, -1); return;
164 case HOME_KEY:
165 if( msgbuf.Qualifier & CTRLKEYS ) move_to_line(p,0,LINE_AS_IS);
166 else horiz_pos(p,0);
167 return;
168 case END_KEY:
169 if( msgbuf.Qualifier & CTRLKEYS ) move_to_line(p,p->max_lines-1,LINE_AS_IS);
170 else horiz_pos(p,MAXPOS);
171 return;
173 case RAWKEY_NM_WHEEL_UP:
174 scroll_ydelta(p, -3);
175 return;
177 case RAWKEY_NM_WHEEL_DOWN:
178 scroll_ydelta(p, 3);
179 return;
180 #endif
182 #if DEBUG
183 case F1_KEY:
184 printf("mask = 0x%02x\n", RP->Mask); return;
185 case F2_KEY:
186 show_modifs(&p->undo); return;
187 case F3_KEY:
188 show_modifs(&p->redo); return;
189 #endif
192 /* Translate key (with dead one) using keymap library */
193 ie.ie_Code = msgbuf.Code;
194 ie.ie_EventAddress = *((APTR *)msgbuf.IAddress);
196 /* Look if CTRL qualifier is used */
197 if( msgbuf.Qualifier & (CTRLKEYS|AMIGAKEYS) )
199 /* Discard qualifiers, if CTRL+<a-z> is pressed a control char will **
200 ** be returned, which does not reflect the key we want to process. */
201 ie.ie_Qualifier = msgbuf.Qualifier & ~(CTRLKEYS | AMIGAKEYS | IEQUALIFIER_CAPSLOCK);
203 /* If it's not a known shortcut, insert control char instead */
204 if(MapRawKey(&ie, buffer, 8, NULL) > 0)
206 if( msgbuf.Qualifier & AMIGAKEYS )
208 /* This is too annoying to insert into menus: Amiga+2~9 enable **
209 ** to quickly change tabstop of current project (not in prefs) */
210 if( '2' <= *buffer && *buffer <= '9' )
212 WORD tabstop = *buffer - '0';
213 if(tabstop != p->tabsize)
214 p->tabsize = tabstop, inv_curs(p, FALSE),
215 active_project(p, FALSE);
216 return;
219 /* CTRL + `1' ~ `0' => activate project nb. x */
220 else if( '0' <= *buffer && *buffer <= '9' )
222 edit = select_panel(edit,*buffer == '0' ? -10 : '0' - *buffer);
223 return;
225 else switch(*buffer)
227 case '\\':change_case(p, 0); return;
228 case '/': change_case(p, 1); return;
229 case 'j': join_strip(p); return;
230 case 'n': FindPattern(p, 1); return;
231 case 'p': FindPattern(p,-1); return;
232 case 'q': handle_menu(111); return;
233 case 'Q': handle_menu(113); return;
234 case 'r': ReplacePattern(p); return;
235 case 'R': ReplaceAllPat(p); return;
236 case 's': FindWord(p, 1); return;
237 case 'S': FindWord(p,-1); return;
238 case 'z': last_modif(&p->undo, 0); return;
239 case '[': handle_menu(401); return;
240 case ']': handle_menu(402); return;
245 /* Make sure this time qualifiers are taken into account */
246 ie.ie_Qualifier = msgbuf.Qualifier;
248 /* Map RAWKEY to ANSI (dead keys return 0) */
249 if(MapRawKey(&ie, buffer, 8, NULL) > 0)
251 /* register UBYTE code = *buffer; */
253 /* Inserting one char is the most common operation **
254 ** and therefore needs to be highly optimized: */
255 if( add_char(&p->undo, p->edited, p->nbc, *buffer) )
257 REDRAW_CURLINE(p);
258 curs_right(p, FALSE);
259 } else ThrowError(Wnd, ErrMsg(ERR_NOMEM));
261 if(record) reg_act_addchar( *buffer ), record |= 0x80;
265 /*** Handle menu related events ***/
266 void handle_menu( LONG MenuID )
268 static UBYTE shift;
270 shift = (msgbuf.Qualifier & SHIFTKEYS ? 1 : 0);
272 switch( MenuID )
274 case 101: /* New file */
275 { Project new;
276 BusyWindow(Wnd);
277 if( ( new = new_project(edit, &prefs) ) )
279 /* Compute panel tabs size */
280 inv_curs(edit, FALSE);
281 reshape_panel(new);
282 active_project(edit=new, TRUE);
284 } else ThrowError(Wnd, ErrMsg(ERR_NOMEM));
285 WakeUp(Wnd);
286 } break;
287 case 102: /* Split open */
288 { STRPTR path;
289 /* Ask a new file name, using the same working directory as current document */
290 if(NULL != (path = ask_load(Wnd, (AskArgs *)&edit->path, FALSE, GetMenuText(102))))
292 Project new;
293 /* Use current project if it is empty and unmodified */
294 if( (new = load_and_activate(edit, path, (edit->path == NULL && (edit->state & MODIFIED) == 0) ? 2 : 3) ) )
295 edit = new;
297 } break;
298 case 103: /* Open (in current panel) */
299 if( warn_modif(edit) )
301 if( shift == 0 )
303 STRPTR path;
304 if(NULL != (path = ask_load(Wnd, (AskArgs *)&edit->path, TRUE, GetMenuText(103))))
305 load_and_activate(edit, path, 1);
307 else reload_project( edit );
308 } break;
309 case 105: /* Save */
310 if(0 == shift) goto case_sav;
312 case 106: save_project (edit,TRUE,TRUE); break; /* Save as */
313 case_sav: save_project (edit,TRUE,FALSE); break; /* Save one file */
314 case 107: save_projects(edit,FALSE); break; /* Save changes */
315 case 108: print_project (edit); break; /* Print project */
316 case 109: show_info(edit); break; /* Information */
318 case 113: /* Save if necessary, then quit */
319 if((edit->state & MODIFIED) && save_project(edit, TRUE, FALSE) == 0)
320 break;
321 case 111: /* Close project */
322 { Project new = edit->prev;
323 if(new == NULL) new = edit->next;
324 /* Check if there were modifications */
325 if( close_project(edit) )
327 /* If there is another opened project, shows it */
328 inv_curs(edit,FALSE); FreeVec(edit);
329 if( new != NULL )
330 reshape_panel(new),
331 active_project(edit = new, FALSE);
332 else
333 /* Otherwise quits */
334 cleanup(0,0);
336 } break;
337 case 112: /* Quit */
338 /* Modified project not yet saved */
339 inv_curs(edit, FALSE);
340 if(NULL != (edit = (shift ? save_projects(edit, TRUE) : close_projects())))
341 reshape_panel(edit),
342 active_project(edit, FALSE);
343 else
344 cleanup(0,0);
345 break;
346 case 201: /* Cut */
347 case 202: /* Copy to clipboard */
348 if( edit->ccp.select == 0 ) break;
350 if( CBWriteFTXT(edit->ccp.yc > edit->ccp.yp ? edit->ccp.line : edit->ccp.cline, &edit->ccp) ) {
351 if( MenuID == 202 ) unmark_all(edit,TRUE);
352 else del_block( edit );
354 break;
355 case 203: /* Paste from clipboard */
356 { LONG buf[3];
357 /* Read chars */
358 if( !CBReadCHRS(&edit->undo, edit->edited, edit->nbc, buf) )
359 /* CBReadCHRS will show the right error */
360 break;
362 /* Just one line concerned? */
363 edit->max_lines += buf[2];
364 if( buf[1] == 0 ) REDRAW_CURLINE(edit)
366 /* Move cursor to the end of pasted text? */
367 if( shift == 0 ) move_cursor(edit,buf[0],buf[1]);
368 if( buf[1]>0 ) redraw_content(edit,edit->show,gui.topcurs,gui.nbline);
369 if( edit->ccp.select ) move_selection(edit, edit->nbrc, edit->nbl);
370 inv_curs(edit,TRUE); prop_adj(edit);
371 } break;
372 case 204: /* Mark text */
373 if(shift) MenuID=205;
374 case 205: /* Mark columnar */
375 move_selection = SwitchSelect(edit,MenuID-204,0);
376 break;
377 case 206: mark_all(edit); break; /* Select all */
378 case 207: amiga_k(edit); break; /* Del line */
379 case 2071: indent_by(edit,'\t', 1); break; /* Indent */
380 case 2072: indent_by(edit,'\t',-1); break; /* Unindent */
381 case 2073: change_case(edit,0); break; /* Upper */
382 case 2074: change_case(edit,1); break; /* Lower */
383 case 2075: change_case(edit,2); break; /* Toggle */
384 case 208: insert_file(edit); break; /* Insert file */
385 case 209:
386 if(shift == 0) {
387 rollback(&edit->undo); break; /* Undo */
389 case 210: rollback(&edit->redo); break; /* Redo */
390 case 301: setup_winsearch(edit,0); break; /* Search */
391 case 302: setup_winsearch(edit,1); break; /* Replace */
392 case 3031: FindPattern(edit, 1); break; /* Find next */
393 case 3032: FindPattern(edit,-1); break; /* Find prev */
394 case 3033: ReplacePattern(edit); break; /* Replace next */
395 case 304: pg_updown(edit,-1); break; /* PgUp */
396 case 305: pg_updown(edit, 1); break; /* PgDown */
397 case 306: goto_line(edit); break; /* Goto line */
398 case 307: match_bracket(edit); break; /* Match bracket */
399 case 308: last_modif(&edit->undo,0); break; /* Last modif */
400 case 309: horiz_pos(edit,0); break; /* Home */
401 case 310: horiz_pos(edit,MAXPOS); break; /* End */
402 case 401: start_macro(); break; /* Record */
403 case 402: stop_macro(); break; /* Stop recording */
404 case 403:
405 if(shift == 0) { play_macro(1); break; } /* Play current macro */
406 case 404: repeat_macro(edit); break; /* Repeat one or more times */
407 case 501: ask_new_screen(); break; /* Change screen mode */
408 case 502: ask_new_font(); break; /* Change text font */
409 case 503: setup_winpref(); break; /* General prefs */
410 case 505: save_prefs(&prefs); break; /* Save prefs */
412 case 504: ask_prefs(edit,0,GetMenuText(504)); break; /* Load prefs */
413 case 506: ask_prefs(edit,1,GetMenuText(506)); break; /* Save prefs as */
418 /** Public port of Jano **/
419 static struct MsgPort *port = NULL, *reply;
420 static struct JPacket *cmd = NULL;
422 UBYTE *PortName = JANO_PORT;
424 /** Look if jano is already running **/
425 char find_janoed( StartUpArgs *args )
427 ULONG sigwait;
428 if( (reply = (struct MsgPort *) FindPort(PortName)) )
430 PortName = NULL; /* Private port */
431 if( ( sigwait = create_port() ) )
433 /* Send to JanoEditor that someone tries to start it again */
434 cmd->class = CMD_NEWEDIT;
435 cmd->msg.args = args;
436 PutMsg(reply, (struct Message *)cmd);
437 /* cmd packet is associated with "port", thus reply will be done here */
438 Wait( sigwait | SIGBREAKF_CTRL_C );
439 /* Unqueue message */
440 GetMsg( port );
442 /* Cleanup will be done later */
443 return 1;
444 } else return 0;
447 /** Setup public port of the editor **/
448 ULONG create_port( void )
450 /* Create a port and */
451 if( ( port = (struct MsgPort *) CreateMsgPort() ) )
453 /* Set this port public */
454 port->mp_Node.ln_Name = PortName;
455 port->mp_Node.ln_Pri = 0;
456 AddPort( port );
458 /* Create a message that can be sent to the editor */
459 if( ( cmd = (struct JPacket *) CreateIORequest(port, (long) sizeof (*cmd)) ) )
460 return (ULONG)(1 << port->mp_SigBit);
462 DeletePort(port);
464 return 0;
467 /** Send a command to preference tool **/
468 char send_pref(PREFS *prefs, ULONG class)
470 /* The port can be shutted down at any time! */
471 if( ( reply = (struct MsgPort *) FindPort(JANOPREFS_PORT)) )
473 cmd->class = class;
474 CopyMem(prefs, &cmd->msg.prefs, sizeof(*prefs));
476 PutMsg(reply, (struct Message *)cmd);
477 Wait( 1 << port->mp_SigBit | SIGBREAKF_CTRL_C );
478 GetMsg( port );
479 return 1;
480 } else return 0;
483 /** Shutdown port **/
484 void close_port( void )
486 if( cmd ) DeleteExtIO((struct IORequest *)cmd);
487 if( port ) RemPort(port), DeleteMsgPort(port);
490 /*** Handle messages posted to public port of Jano ***/
491 void handle_port( void )
493 struct JPacket *msg; char update = 0;
494 extern PREFS tmpprefs;
495 while( ( msg = (struct JPacket *) GetMsg(port) ) )
497 switch( msg->class )
499 case CMD_NEWEDIT:
500 /* Look if there are projects to load */
501 if(msg->msg.args->sa_NbArgs > 0)
503 inv_curs(edit, FALSE);
504 edit = create_projects(edit, msg->msg.args->sa_ArgLst, msg->msg.args->sa_NbArgs);
505 reshape_panel(edit);
506 active_project(edit,TRUE);
507 clear_brcorner();
509 case CMD_SHOW:
510 WindowToFront( Wnd );
511 ScreenToFront( Scr );
512 ActivateWindow( Wnd );
513 break;
514 case CMD_KILL: cleanup(0,0); break;
515 case CMD_PREF:
516 /* Send a copy of preference struct */
517 prefs.current = Scr;
518 CopyMem(&prefs, &msg->msg.prefs, sizeof(prefs));
519 break;
520 case CMD_SAVPREF: update = 2; goto save;
521 case CMD_NEWPREF: update = 1;
522 /* Preference tool has sent a new config! */
523 save: CopyMem(&msg->msg.prefs, &tmpprefs, sizeof(tmpprefs)); break;
525 ReplyMsg((struct Message *)msg);
527 /* Preferences have changed? */
528 if(update == 2) save_prefs(&tmpprefs);
529 if(update >= 1) update_prefs(edit);