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 */
13 #include "IPC_Prefs.h"
19 #include "ProtoTypes.h"
21 #define CATCOMP_NUMBERS /* String ID for ErrMsg() */
24 static struct InputEvent ie
= {0,IECLASS_RAWKEY
}; /* Keyboard translation map */
25 extern struct IntuiMessage msgbuf
;
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
)))
42 /* Clear CONTROL qualifier, if no PC keypad emulation */
43 msgbuf
.Qualifier
&= ~CTRLKEYS
;
45 shift
= (msgbuf
.Qualifier
& SHIFTKEYS
? 1 : 0);
51 /* Switch with replacement cursor */
52 p
->cursmode
= !p
->cursmode
;
53 inv_curs(p
, FALSE
); inv_curs(p
, TRUE
);
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;
61 /* Amiga space indent line */
62 if( msgbuf
.Qualifier
& AMIGAKEYS
) {
63 indent_by(p
, ' ', shift
? -1:1); return;
66 if( msgbuf
.Qualifier
& AMIGAKEYS
) {
67 indent_by(p
, '\t',shift
? -1:1); return;
72 else if( msgbuf
.Qualifier
& AMIGAKEYS
)
77 back_space(p
, (msgbuf
.Qualifier
& ALTKEYS
) != 0);
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;
91 del(p
, (msgbuf
.Qualifier
& ALTKEYS
) != 0);
93 case N8_KEY
: if( *buffer
== 0 ) break;
95 if( msgbuf
.Qualifier
& CTRLKEYS
)
96 move_to_line(p
,0,LINE_AS_IS
);
98 if( msgbuf
.Qualifier
& ALTKEYS
)
105 case N2_KEY
: if( *buffer
== 0 ) break;
107 if( msgbuf
.Qualifier
& CTRLKEYS
)
108 move_to_line(p
,p
->max_lines
-1,LINE_AS_IS
);
110 if( msgbuf
.Qualifier
& ALTKEYS
)
117 case N6_KEY
: if( *buffer
== 0 ) break;
118 case RIGHT_KEY
: /* Used for various things! */
119 if( msgbuf
.Qualifier
& CTRLKEYS
)
121 edit
= select_panel(edit
, NEXT_PROJECT
);
125 if( msgbuf
.Qualifier
& ALTKEYS
)
126 scroll_xdelta(p
, gui
.xstep
);
130 curs_right(p
, (msgbuf
.Qualifier
& ALTKEYS
) != 0);
132 case N4_KEY
: if( *buffer
== 0 ) break;
134 if( msgbuf
.Qualifier
& CTRLKEYS
)
136 edit
= select_panel(edit
, PREV_PROJECT
);
140 if( msgbuf
.Qualifier
& ALTKEYS
)
141 scroll_xdelta(p
, -gui
.xstep
);
145 curs_left(p
, (msgbuf
.Qualifier
& ALTKEYS
) != 0);
149 if( msgbuf
.Qualifier
& CTRLKEYS
)
151 STRPTR path
= GetIncludeFile(p
, p
->edited
);
154 if(NULL
!= path
&& (shift
== 0 || warn_modif(edit
)))
155 new = load_and_activate(edit
, path
, shift
);
163 case PGDOWN_KEY
: pg_updown(p
, 1); return;
164 case PGUP_KEY
: pg_updown(p
, -1); return;
167 if( msgbuf
.Qualifier
& CTRLKEYS
) move_to_line(p
,0,LINE_AS_IS
);
171 if( msgbuf
.Qualifier
& CTRLKEYS
) move_to_line(p
,p
->max_lines
-1,LINE_AS_IS
);
172 else horiz_pos(p
,MAXPOS
);
175 case RAWKEY_NM_WHEEL_UP
:
176 scroll_ydelta(p
, -3);
179 case RAWKEY_NM_WHEEL_DOWN
:
186 printf("mask = 0x%02x\n", RP
->Mask
); return;
188 show_modifs(&p
->undo
); return;
190 show_modifs(&p
->redo
); return;
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
);
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
);
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
) )
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
)
272 shift
= (msgbuf
.Qualifier
& SHIFTKEYS
? 1 : 0);
276 case 101: /* New file */
279 if( ( new = new_project(edit
, &prefs
) ) )
281 /* Compute panel tabs size */
282 inv_curs(edit
, FALSE
);
284 active_project(edit
=new, TRUE
);
286 } else ThrowError(Wnd
, ErrMsg(ERR_NOMEM
));
289 case 102: /* Split open */
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))))
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) ) )
300 case 103: /* Open (in current panel) */
301 if( warn_modif(edit
) )
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
);
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)
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
);
333 active_project(edit
= new, FALSE
);
335 /* Otherwise quits */
340 /* Modified project not yet saved */
341 inv_curs(edit
, FALSE
);
342 if(NULL
!= (edit
= (shift
? save_projects(edit
, TRUE
) : close_projects())))
344 active_project(edit
, FALSE
);
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
);
357 case 203: /* Paste from clipboard */
360 if( !CBReadCHRS(&edit
->undo
, edit
->edited
, edit
->nbc
, buf
) )
361 /* CBReadCHRS will show the right error */
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
);
374 case 204: /* Mark text */
375 if(shift
) MenuID
=205;
376 case 205: /* Mark columnar */
377 move_selection
= SwitchSelect(edit
,MenuID
-204,0);
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 */
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 */
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
)
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 */
444 /* Cleanup will be done later */
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;
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
);
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
)) )
476 CopyMem(prefs
, &cmd
->msg
.prefs
, sizeof(*prefs
));
478 PutMsg(reply
, (struct Message
*)cmd
);
479 Wait( 1 << port
->mp_SigBit
| SIGBREAKF_CTRL_C
);
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
) ) )
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
);
508 active_project(edit
,TRUE
);
512 WindowToFront( Wnd
);
513 ScreenToFront( Scr
);
514 ActivateWindow( Wnd
);
516 case CMD_KILL
: cleanup(0,0); break;
518 /* Send a copy of preference struct */
520 CopyMem(&prefs
, &msg
->msg
.prefs
, sizeof(prefs
));
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
);