/* * This file implements memacs support for the Amiga mouse. * Author: Andy Poggio */ #include #include #include #include #include #include "ed.h" #define NL 0 extern struct Window *Window; /* Font sizes */ #define FONT_X 8 #define FONT_Y 8 /* Button Codes */ #define LEFT_BUTTON 1 #define RIGHT_BUTTON 2 /* Copies of this structure will get "stamped" into many more */ /* Allocated later */ struct IntuiText generic = { 0, 1, /* Bluepen, Whitepen */ JAM2, 5, /* mode, LeftEdge */ 0, NL, /* Top (to be filled later), Font */ NL, /* Name (to be filled later) */ NL /* Next one */ }; #define NUM_MENUS 4 /* Menu numbers */ #define PRO_MENU 0 #define REG_MENU 1 #define COM_MENU 2 #define OPT_MENU 3 /* Menu Widths */ #define COM_WIDTH 72 #define ITEM_WIDTH 112 /* All items in these menus have the following flags set */ #define BLACK_FILL ITEMTEXT | ITEMENABLED | HIGHCOMP /** FILE MENU ITEMS **/ #define NUM_PRO_ITEMS 6 #define NUM_REG_ITEMS 4 #define NUM_COM_ITEMS 7 #define NUM_OPT_ITEMS 6 #define NEWBUF_ITEM 0 #define OPEN_ITEM 1 #define SAVE_ITEM 2 #define SAVEAS_ITEM 3 #define QUITNSAVE_ITEM 4 #define QUIT_ITEM 5 #define KILL_ITEM 0 #define COPY_ITEM 1 #define UNKILL_ITEM 2 #define FILEYANK_ITEM 3 #define NOOP_ITEM 0 #define SEARCH_ITEM 1 #define QUERY_ITEM 2 #define STARTM_ITEM 3 #define ENDM_ITEM 4 #define EXECM_ITEM 5 #define NEW_ITEM 6 #define TWO_ITEM 0 #define ONE_ITEM 1 #define AUTOIND_ITEM 2 #define WORDRAP_ITEM 3 #define LEFTMAR_ITEM 4 #define RIGHTMAR_ITEM 5 struct MenuItem pro_items[NUM_PRO_ITEMS]; struct IntuiText pro_names[NUM_PRO_ITEMS]; struct MenuItem reg_items[NUM_REG_ITEMS]; struct IntuiText reg_names[NUM_REG_ITEMS]; struct MenuItem com_items[NUM_COM_ITEMS]; struct IntuiText com_names[NUM_COM_ITEMS]; struct MenuItem opt_items[NUM_OPT_ITEMS]; struct IntuiText opt_names[NUM_OPT_ITEMS]; char *promenu_names[] = { "New Buffer ", "Open ", "Save ", "Save As ", "Quit & Save", "Quit " }; char *regmenu_names[] = { "Cut ", "Copy ", "Paste ", "File Paste " }; char *commenu_names[] = { "No Operaton ", "Search ", "Replace ", "Start Macro ", "End Macro ", "Execute Macro", "New CLI " }; char *optmenu_names[] = { "Split Window", "One Window ", "Auto indent ", "Word wrap ", "Left Margin ", "Right Margin" }; struct Menu pmenu = { NULL, /* Pointer to next menu */ 0, 0, COM_WIDTH, 10, /* LeftEdge, TopEdge, Width, Height */ MENUENABLED, /* FLAGS */ "Project", /* Menu name */ pro_items /* First item structure */ }; struct Menu rmenu = { NULL, /* Pointer to next menu */ COM_WIDTH, 0, COM_WIDTH, 10, /* LeftEdge, TopEdge, Width, Height */ MENUENABLED, /* FLAGS */ "Region", /* Menu name */ reg_items /* First item structure */ }; struct Menu cmenu = { NULL, /* Pointer to next menu */ COM_WIDTH*2, 0, COM_WIDTH, 10, /* LeftEdge, TopEdge, Width, Height */ MENUENABLED, /* FLAGS */ "Commands", /* Menu name */ com_items /* First item structure */ }; struct Menu omenu = { NULL, /* Pointer to next menu */ COM_WIDTH*3, 0, COM_WIDTH, 10, /* LeftEdge, TopEdge, Width, Height */ MENUENABLED, /* FLAGS */ " Options", /* Menu name */ opt_items /* First item structure */ }; mouse_setup_menu() { mouse_newmenu( &pmenu, promenu_names, pro_items, pro_names, NUM_PRO_ITEMS, ITEM_WIDTH, BLACK_FILL); mouse_newmenu( &rmenu, regmenu_names, reg_items, reg_names, NUM_REG_ITEMS, ITEM_WIDTH, BLACK_FILL); mouse_newmenu( &cmenu, commenu_names, com_items, com_names, NUM_COM_ITEMS, ITEM_WIDTH, BLACK_FILL); mouse_newmenu( &omenu, optmenu_names, opt_items, opt_names, NUM_OPT_ITEMS, ITEM_WIDTH, BLACK_FILL); pmenu.NextMenu = &rmenu; rmenu.NextMenu = &cmenu; cmenu.NextMenu = &omenu; reg_items[0].Command = 'X'; reg_items[1].Command = 'C'; reg_items[2].Command = 'P'; reg_items[0].Flags |= COMMSEQ; reg_items[1].Flags |= COMMSEQ; reg_items[2].Flags |= COMMSEQ; SetMenuStrip(Window, &pmenu); /* Set up the menu here */ } mouse_clear_menu() { ClearMenuStrip(Window, &cmenu); } static do_menu( m, f, n) /* execute a menu command */ { int menu, item, sub; menu = MENUNUM( m); item = ITEMNUM( m); sub = SUBNUM( m); if( kbdmip != NULL) /* collecting macro */ { if ( menu == COM_MENU && item == ENDM_ITEM ) /* End macro */ ; else { ctrlg(FALSE, 0); return( FALSE ); } } switch( menu) { case PRO_MENU: switch( item) { case NEWBUF_ITEM: usebuffer( f, n); break; case OPEN_ITEM: fileread( f, n); break; case SAVE_ITEM: filesave( f, n); break; case SAVEAS_ITEM: filewrite( f, n); break; case QUITNSAVE_ITEM: quickexit( f, n); break; case QUIT_ITEM: quit( f, n); break; } break; case REG_MENU: switch( item) { case COPY_ITEM: copyregion( f, n); break; case KILL_ITEM: killregion( f, n); break; case UNKILL_ITEM: yank( f, n); break; case FILEYANK_ITEM: fileyank( f, n); break; } break; case COM_MENU: switch( item) { case NOOP_ITEM: break; case SEARCH_ITEM: forwsearch( f, n); break; case QUERY_ITEM: qreplace( f, n); break; case STARTM_ITEM: ctlxlp( f, n); break; case ENDM_ITEM: ctlxrp( f, n); break; case EXECM_ITEM: ctlxe( f, n); break; case NEW_ITEM: spawncli( f, n); break; } break; case OPT_MENU: switch( item ) { case TWO_ITEM: splitwind( f, n); break; case ONE_ITEM: onlywind( f, n); break; case WORDRAP_ITEM: togglewordwrap( f, n); break; case AUTOIND_ITEM: toggleautoindent( f, n); break; case LEFTMAR_ITEM: setfillcol( 0, n); break; case RIGHTMAR_ITEM: setfillcol( 1, n); break; } break; default: break; } } mouse_handle_event( f, n) { register char *s; int result, c, class, subclass, keycode, qualifiers, x, y, secs, musecs; char instr[ 88 ]; /* 8 nine digit numbers with separators + 1 */ static int netx, nety; static int button_now = 0, button_ever = 0; for ( s = instr; (*s++ = ttgetc()) != '|';) ; *s = 0; /* terminate the str */ sscanf( instr, "%d;%d;%d;%d;%d;%d;%d;%d|", &class, &subclass, &keycode, &qualifiers, &x, &y, &secs, &musecs); switch( class) { case 2: /* mouse button--only get this for left button */ if( keycode & 0x80) /* key up */ { keycode &= ~0x80; /* clear the up bit */ button_now &= ~ LEFT_BUTTON; } else /* key down */ { netx = Window->MouseX - Window->BorderLeft; /* save coords */ nety = Window->MouseY - Window->BorderTop; button_now |= LEFT_BUTTON; button_ever |= LEFT_BUTTON; } break; case 10: /* menu selection -- right button up only */ if( keycode == MENUNULL) { netx = Window->MouseX - Window->BorderLeft; /* save coords */ nety = Window->MouseY - Window->BorderTop; button_ever |= RIGHT_BUTTON; } else /* made a menu selection */ { button_ever = 0; /* ignore other buttons */ do_menu( keycode, f, n); } break; } if ( (!button_now) && button_ever ) /* buttons were pushed: interpret */ { switch( button_ever) { case LEFT_BUTTON: mouse_to_xy( netx, nety); break; case RIGHT_BUTTON: mouse_set_mark( netx, nety); break; case LEFT_BUTTON | RIGHT_BUTTON: forwdel( f, n); break; } button_ever = 0; } } mouse_newmenu( menu, item_names, menu_items, menu_text, num_items, Mwidth, flag) struct Menu *menu; /* Menu structure */ char *item_names[]; /* Pointer to array of item names */ struct MenuItem menu_items[]; /* pointer to array of structures */ struct IntuiText menu_text[]; /* Pointer to array of text structures */ int num_items; /* Number of items */ int Mwidth; /* Menu Width */ int flag; /* Special Item flag for ALL items */ { int i; int height = 0; for (i=0; i< num_items; i++) { menu_text[i] = generic; /* stamp generic template */ menu_text[i].IText = (UBYTE *) item_names[i]; /* mv string ptrs */ menu_items[i].NextItem = &menu_items[i+1]; /* Lnk to nxt item */ menu_items[i].TopEdge = 10 * i; /* Top rect of item */ menu_items[i].LeftEdge = 0; menu_items[i].Height = 8; menu_items[i].ItemFill = (APTR)&menu_text[i]; menu_items[i].Flags = flag; menu_items[i].Width = Mwidth; menu_items[i].MutualExclude = 0x0000; menu_items[i].Command = 0; menu_items[i].SubItem = NL; menu_items[i].NextSelect = NL; height += 10; } menu_items[num_items-1].NextItem = NULL; menu->Height = height; } static winddist( w, row, col) /* calc distance of window from this row, col */ WINDOW *w; { int d; if( row < w->w_toprow) /* above window */ return( w->w_toprow - row); else if( row < (w->w_toprow + w->w_ntrows)) /* within window */ return( 0); else /* below window */ return( row - (w->w_toprow + w->w_ntrows)); } WINDOW * mouse_find_wind( row, col) /* find window containing this row, col */ { WINDOW *w, *result_w; int distance, result_distance; result_distance = HUGE; /* greater than any real distance */ for( w = wheadp; w != NULL; w = w->w_wndp) { distance = winddist( w, row, col); if( distance < result_distance) { result_w = w; result_distance = distance; } } return( result_w); } static get_wintop( this_w) /* return row for top of this window */ WINDOW *this_w; { register WINDOW *w; register int row; row = 0; for( w = wheadp; w != this_w; w = w->w_wndp) { row += w->w_ntrows +1; } return( row); } mouse_to_xy( x, y) /* move point to position at coords x,y */ { register LINE *dlp; register int row, col; WINDOW *w; row = y / FONT_Y; /* convert coords to row and col */ col = x / FONT_X; w = mouse_find_wind( row, col); /* find the window and make it current */ curwp = w; curbp = curwp->w_bufp; row -= get_wintop( curwp); /* adjust to row in window */ if( row >= curwp->w_ntrows) row = curwp->w_ntrows -1; dlp = curwp->w_linep; while (row-- && dlp!=curbp->b_linep) { dlp = lforw(dlp); } curwp->w_dotp = dlp; curgoal = col; /* aim for this col */ curwp->w_doto = getgoal(dlp); } mouse_set_mark( x, y) /* set mark at mouse cursor */ { WINDOW *wp; LINE *dlp; int offset; /* save current position */ wp = curwp; dlp = curwp->w_dotp; offset = curwp->w_doto; /* go to cursor position, set mark, and announce */ mouse_to_xy( x, y); update(); setmark( FALSE, 1); update(); /* return to former position */ curwp = wp; curbp = curwp->w_bufp; curwp->w_dotp = dlp; curwp->w_doto = offset; } mouse_enable() /* this must be last to keep ctags happy */ { ttputs( "\x1b[2;10{"); /* get mouse button and menu events */ ttflush(); }