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 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)
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
);
331 active_project(edit
= new, FALSE
);
333 /* Otherwise quits */
338 /* Modified project not yet saved */
339 inv_curs(edit
, FALSE
);
340 if(NULL
!= (edit
= (shift
? save_projects(edit
, TRUE
) : close_projects())))
342 active_project(edit
, FALSE
);
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
);
355 case 203: /* Paste from clipboard */
358 if( !CBReadCHRS(&edit
->undo
, edit
->edited
, edit
->nbc
, buf
) )
359 /* CBReadCHRS will show the right error */
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
);
372 case 204: /* Mark text */
373 if(shift
) MenuID
=205;
374 case 205: /* Mark columnar */
375 move_selection
= SwitchSelect(edit
,MenuID
-204,0);
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 */
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 */
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
)
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 */
442 /* Cleanup will be done later */
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;
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
);
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
)) )
474 CopyMem(prefs
, &cmd
->msg
.prefs
, sizeof(*prefs
));
476 PutMsg(reply
, (struct Message
*)cmd
);
477 Wait( 1 << port
->mp_SigBit
| SIGBREAKF_CTRL_C
);
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
) ) )
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
);
506 active_project(edit
,TRUE
);
510 WindowToFront( Wnd
);
511 ScreenToFront( Scr
);
512 ActivateWindow( Wnd
);
514 case CMD_KILL
: cleanup(0,0); break;
516 /* Send a copy of preference struct */
518 CopyMem(&prefs
, &msg
->msg
.prefs
, sizeof(prefs
));
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
);