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
);
159 else split_curline( p
); return;
161 case PGDOWN_KEY
: pg_updown(p
, 1); return;
162 case PGUP_KEY
: pg_updown(p
, -1); return;
165 if( msgbuf
.Qualifier
& CTRLKEYS
) move_to_line(p
,0,LINE_AS_IS
);
169 if( msgbuf
.Qualifier
& CTRLKEYS
) move_to_line(p
,p
->max_lines
-1,LINE_AS_IS
);
170 else horiz_pos(p
,MAXPOS
);
173 case RAWKEY_NM_WHEEL_UP
:
174 scroll_ydelta(p
, -3);
177 case RAWKEY_NM_WHEEL_DOWN
:
184 printf("mask = 0x%02x\n", RP
->Mask
); return;
186 show_modifs(&p
->undo
); return;
188 show_modifs(&p
->redo
); return;
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
);
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
);
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
) )
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
)
270 shift
= (msgbuf
.Qualifier
& SHIFTKEYS
? 1 : 0);
274 case 101: /* New file */
277 if( ( new = new_project(edit
, &prefs
) ) )
279 /* Compute panel tabs size */
280 inv_curs(edit
, FALSE
);
282 active_project(edit
=new, TRUE
);
284 } else ThrowError(Wnd
, ErrMsg(ERR_NOMEM
));
287 case 102: /* Split open */
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))))
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) ) )
298 case 103: /* Open (in current panel) */
299 if( warn_modif(edit
) )
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
);
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 109: show_info(edit
); break; /* Information */
317 case 113: /* Save if necessary, then quit */
318 if((edit
->state
& MODIFIED
) && save_project(edit
, TRUE
, FALSE
) == 0)
320 case 111: /* Close project */
321 { Project
new = edit
->prev
;
322 if(new == NULL
) new = edit
->next
;
323 /* Check if there were modifications */
324 if( close_project(edit
) )
326 /* If there is another opened project, shows it */
327 inv_curs(edit
,FALSE
); FreeVec(edit
);
330 active_project(edit
= new, FALSE
);
332 /* Otherwise quits */
337 /* Modified project not yet saved */
338 inv_curs(edit
, FALSE
);
339 if(NULL
!= (edit
= (shift
? save_projects(edit
, TRUE
) : close_projects())))
341 active_project(edit
, FALSE
);
346 case 202: /* Copy to clipboard */
347 if( edit
->ccp
.select
== 0 ) break;
349 if( CBWriteFTXT(edit
->ccp
.yc
> edit
->ccp
.yp
? edit
->ccp
.line
: edit
->ccp
.cline
, &edit
->ccp
) ) {
350 if( MenuID
== 202 ) unmark_all(edit
,TRUE
);
351 else del_block( edit
);
354 case 203: /* Paste from clipboard */
357 if( !CBReadCHRS(&edit
->undo
, edit
->edited
, edit
->nbc
, buf
) )
358 /* CBReadCHRS will show the right error */
361 /* Just one line concerned? */
362 edit
->max_lines
+= buf
[2];
363 if( buf
[1] == 0 ) REDRAW_CURLINE(edit
)
365 /* Move cursor to the end of pasted text? */
366 if( shift
== 0 ) move_cursor(edit
,buf
[0],buf
[1]);
367 if( buf
[1]>0 ) redraw_content(edit
,edit
->show
,gui
.topcurs
,gui
.nbline
);
368 if( edit
->ccp
.select
) move_selection(edit
, edit
->nbrc
, edit
->nbl
);
369 inv_curs(edit
,TRUE
); prop_adj(edit
);
371 case 204: /* Mark text */
372 if(shift
) MenuID
=205;
373 case 205: /* Mark columnar */
374 move_selection
= SwitchSelect(edit
,MenuID
-204,0);
376 case 206: mark_all(edit
); break; /* Select all */
377 case 207: amiga_k(edit
); break; /* Del line */
378 case 2071: indent_by(edit
,'\t', 1); break; /* Indent */
379 case 2072: indent_by(edit
,'\t',-1); break; /* Unindent */
380 case 2073: change_case(edit
,0); break; /* Upper */
381 case 2074: change_case(edit
,1); break; /* Lower */
382 case 2075: change_case(edit
,2); break; /* Toggle */
383 case 208: insert_file(edit
); break; /* Insert file */
386 rollback(&edit
->undo
); break; /* Undo */
388 case 210: rollback(&edit
->redo
); break; /* Redo */
389 case 301: setup_winsearch(edit
,0); break; /* Search */
390 case 302: setup_winsearch(edit
,1); break; /* Replace */
391 case 3031: FindPattern(edit
, 1); break; /* Find next */
392 case 3032: FindPattern(edit
,-1); break; /* Find prev */
393 case 3033: ReplacePattern(edit
); break; /* Replace next */
394 case 304: pg_updown(edit
,-1); break; /* PgUp */
395 case 305: pg_updown(edit
, 1); break; /* PgDown */
396 case 306: goto_line(edit
); break; /* Goto line */
397 case 307: match_bracket(edit
); break; /* Match bracket */
398 case 308: last_modif(&edit
->undo
,0); break; /* Last modif */
399 case 309: horiz_pos(edit
,0); break; /* Home */
400 case 310: horiz_pos(edit
,MAXPOS
); break; /* End */
401 case 401: start_macro(); break; /* Record */
402 case 402: stop_macro(); break; /* Stop recording */
404 if(shift
== 0) { play_macro(1); break; } /* Play current macro */
405 case 404: repeat_macro(edit
); break; /* Repeat one or more times */
406 case 501: ask_new_screen(); break; /* Change screen mode */
407 case 502: ask_new_font(); break; /* Change text font */
408 case 503: setup_winpref(); break; /* General prefs */
409 case 505: save_prefs(&prefs
); break; /* Save prefs */
411 case 504: ask_prefs(edit
,0,GetMenuText(504)); break; /* Load prefs */
412 case 506: ask_prefs(edit
,1,GetMenuText(506)); break; /* Save prefs as */
417 /** Public port of Jano **/
418 static struct MsgPort
*port
= NULL
, *reply
;
419 static struct JPacket
*cmd
= NULL
;
421 UBYTE
*PortName
= JANO_PORT
;
423 /** Look if jano is already running **/
424 char find_janoed( StartUpArgs
*args
)
427 if( (reply
= (struct MsgPort
*) FindPort(PortName
)) )
429 PortName
= NULL
; /* Private port */
430 if( ( sigwait
= create_port() ) )
432 /* Send to JanoEditor that someone tries to start it again */
433 cmd
->class = CMD_NEWEDIT
;
434 cmd
->msg
.args
= args
;
435 PutMsg(reply
, (struct Message
*)cmd
);
436 /* cmd packet is associated with "port", thus reply will be done here */
437 Wait( sigwait
| SIGBREAKF_CTRL_C
);
438 /* Unqueue message */
441 /* Cleanup will be done later */
446 /** Setup public port of the editor **/
447 ULONG
create_port( void )
449 /* Create a port and */
450 if( ( port
= (struct MsgPort
*) CreateMsgPort() ) )
452 /* Set this port public */
453 port
->mp_Node
.ln_Name
= PortName
;
454 port
->mp_Node
.ln_Pri
= 0;
457 /* Create a message that can be sent to the editor */
458 if( ( cmd
= (struct JPacket
*) CreateIORequest(port
, (long) sizeof (*cmd
)) ) )
459 return (ULONG
)(1 << port
->mp_SigBit
);
466 /** Send a command to preference tool **/
467 char send_pref(PREFS
*prefs
, ULONG
class)
469 /* The port can be shutted down at any time! */
470 if( ( reply
= (struct MsgPort
*) FindPort(JANOPREFS_PORT
)) )
473 CopyMem(prefs
, &cmd
->msg
.prefs
, sizeof(*prefs
));
475 PutMsg(reply
, (struct Message
*)cmd
);
476 Wait( 1 << port
->mp_SigBit
| SIGBREAKF_CTRL_C
);
482 /** Shutdown port **/
483 void close_port( void )
485 if( cmd
) DeleteExtIO((struct IORequest
*)cmd
);
486 if( port
) RemPort(port
), DeleteMsgPort(port
);
489 /*** Handle messages posted to public port of Jano ***/
490 void handle_port( void )
492 struct JPacket
*msg
; char update
= 0;
493 extern PREFS tmpprefs
;
494 while( ( msg
= (struct JPacket
*) GetMsg(port
) ) )
499 /* Look if there are projects to load */
500 if(msg
->msg
.args
->sa_NbArgs
> 0)
502 inv_curs(edit
, FALSE
);
503 edit
= create_projects(edit
, msg
->msg
.args
->sa_ArgLst
, msg
->msg
.args
->sa_NbArgs
);
505 active_project(edit
,TRUE
);
509 WindowToFront( Wnd
);
510 ScreenToFront( Scr
);
511 ActivateWindow( Wnd
);
513 case CMD_KILL
: cleanup(0,0); break;
515 /* Send a copy of preference struct */
517 CopyMem(&prefs
, &msg
->msg
.prefs
, sizeof(prefs
));
519 case CMD_SAVPREF
: update
= 2; goto save
;
520 case CMD_NEWPREF
: update
= 1;
521 /* Preference tool has sent a new config! */
522 save
: CopyMem(&msg
->msg
.prefs
, &tmpprefs
, sizeof(tmpprefs
)); break;
524 ReplyMsg((struct Message
*)msg
);
526 /* Preferences have changed? */
527 if(update
== 2) save_prefs(&tmpprefs
);
528 if(update
>= 1) update_prefs(edit
);