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