/******************************** * Function Keys 1.1 03/89 * * by Torsten Jürgeleit * * for Manx Aztec C v3.6a * * cc fkeys * * ln fkeys detach -lc * ********************************/ /* Includes */ #include #include #include #include #include #include #include /* Defines */ #define WINDOW_WIDTH 280 #define WINDOW_HEIGHT 180 #define GADGET_REMOVE 0 #define GADGET_CONTINUE 1 #define NEWCLI "NewCLI >NIL: NIL: mp_SigBit) #define SIGF_ACTION (1L << SIGB_ACTION) #define ACTION_NOTHING 0 #define ACTION_NEWCLI 1 #define ACTION_REMOVE_REQUESTER 2 /* Declarations for DETACH (segment list splitting) */ LONG _stack = 0x1000; LONG _priority = 0; LONG _BackGroundIO = 0; BYTE *_procname = "FKeys1.1"; /* Globals */ struct GfxBase *GfxBase; struct IntuitionBase *IntuitionBase; struct LayersBase *LayersBase; struct Task *main_task; struct FileHandle *file_handle; struct MsgPort *input_port; struct IOStdReq *input_req; struct Interrupt interrupt; UBYTE action = ACTION_NOTHING; /* Dummy functions - not used from c.lib */ VOID _cli_parse() {} VOID _wb_parse() {} /* Casts */ VOID interrupt_server(), back_window_to_front(), front_window_to_back(), activate_next_window(), activate_previous_window(), active_window_to_front(), active_window_to_back(), quit_program(), back_screen_to_front(), front_screen_to_back(), newcli(); BOOL remove_requester(); struct Window *top_window(), *bottom_window(), *next_window(), *previous_window(); /* Main - installs interrupt server and performs interrupt action */ VOID main() { BOOL remove = FALSE; main_task = FindTask(NULL); if (file_handle = Open("NIL:", MODE_NEWFILE)) { if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L)) { if (IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0L)) { if (FindPort(_procname)) { DisplayBeep(NULL); } else { if (LayersBase = (struct LayersBase *) OpenLibrary("layers.library", 0L)) { if (input_port = CreatePort(_procname, 0L)) { if (input_req = CreateStdIO(input_port)) { if (! OpenDevice("input.device", 0L, input_req, 0L)) { interrupt.is_Code = (VOID (*)()) &interrupt_server; interrupt.is_Data = NULL; interrupt.is_Node.ln_Name = _procname; interrupt.is_Node.ln_Pri = 51; /* above of Intuition */ input_req->io_Command = IND_ADDHANDLER; input_req->io_Data = (APTR)&interrupt; if (! DoIO(input_req)) { do { Wait(SIGF_ACTION); /* wait for action signal */ switch (action) { case ACTION_NEWCLI : if (WBenchToFront() == FALSE) { DisplayBeep(NULL); } else { Execute(NEWCLI, file_handle, file_handle); } break; case ACTION_REMOVE_REQUESTER : remove = remove_requester(); break; } } while (remove != TRUE); input_req->io_Command = IND_REMHANDLER; DoIO(input_req); DisplayBeep(NULL); } CloseDevice(input_req); } DeleteStdIO(input_req); } DeletePort(input_port); } CloseLibrary(LayersBase); } } CloseLibrary(IntuitionBase); } CloseLibrary(GfxBase); } Close(file_handle); } } /* Interrupt server to parse event list for function key events */ VOID interrupt_server() { #asm IECLASS_NULL EQU $00 IECLASS_RAWKEY EQU $01 IECODEB_KEYUP EQU 7 IECODE_F1KEY EQU $50 IEQUALIFIERB_REPEAT EQU 9 IEQUALIFIER_CAPSLOCK EQU $0004 IEQUALIFIER_LCOMMAND EQU $0040 IEQUALIFIER_REPEAT EQU $0200 IEQUALIFIER_RELATIVEMOUSE EQU $8000 ie_NextEvent EQU $00 ; APTR ie_Class EQU $04 ; UBYTE ie_Code EQU $06 ; UWORD ie_Qualifier EQU $08 ; UWORD XREF _geta4# XREF _function_table ; (called with : a0 = event list ptr , a1 = interrupt data ptr) movem.l a0-a6/d0-d7,-(sp) jsr _geta4# ; Aztec C need it for small code/data model bra.s check_next_event event_loop: cmp.b #IECLASS_RAWKEY,ie_Class(a0) ; check ie_Class bne.s next_event move.w ie_Qualifier(a0),d0 ; check ie_Qualifier move.w d0,d1 ; save ie_Qualifier and.w #~(IEQUALIFIER_RELATIVEMOUSE|IEQUALIFIER_CAPSLOCK|IEQUALIFIER_REPEAT),d0 cmp.w #IEQUALIFIER_LCOMMAND,d0 ; left Amiga key pressed ? bne.s next_event move.w ie_Code(a0),d0 ; check ie_Code btst #IECODEB_KEYUP,d0 ; only key down events bne.s next_event sub.w #IECODE_F1KEY,d0 ; function key pressed ? cmp.w #10,d0 bcc.s next_event btst #IEQUALIFIERB_REPEAT,d1 ; ignore auto repeat bne.s clear_event fkey_pressed: lsl.w #2,d0 lea _function_table,a1 move.l (a1,d0.w),a1 ; a1 := function ptr move.l a0,-(sp) ; save event ptr jsr (a1) ; call function move.l (sp)+,a0 ; restore event ptr clear_event: move.l #IECLASS_NULL,ie_Class(a0) ; clear event next_event: move.l ie_NextEvent(a0),a0 ; get next event in list check_next_event: move.l a0,d0 ; next event ptr == NULL ? bne.s event_loop movem.l (sp)+,a0-a6/d0-d7 move.l a0,d0 ; return event list ptr #endasm } /* Remove and about requester */ struct TextAttr topaz80 = { (STRPTR)"topaz.font", TOPAZ_EIGHTY, 0, 0 }; struct TextAttr topaz60 = { (STRPTR)"topaz.font", TOPAZ_SIXTY, 0, 0 }; SHORT border_vec[] = {0, 0, 81, 0, 81, 21, 0, 21, 0, 0 }; struct Border border = { -1, -1, 0, 0, JAM1, 5, &border_vec[0], NULL }; struct IntuiText remove_text = { 3, 0, JAM1, 16, 6, &topaz80, (UBYTE *) "Remove", NULL }; struct Gadget remove_gadget = { NULL, 20, WINDOW_HEIGHT - 30, 80, 20, GADGHCOMP, RELVERIFY, BOOLGADGET, (APTR)&border, NULL, &remove_text, 0, NULL, GADGET_REMOVE, NULL}; struct IntuiText continue_text = { 3, 0, JAM1, 8, 6, &topaz80, (UBYTE *) "Continue", NULL }; struct Gadget continue_gadget = { &remove_gadget, WINDOW_WIDTH - 100, WINDOW_HEIGHT - 30, 80, 20, GADGHCOMP, RELVERIFY, BOOLGADGET, (APTR) &border, NULL, &continue_text, 0, NULL, GADGET_CONTINUE, NULL}; struct IntuiText usage_text10 = { 2, 0, JAM1, 20, 135, &topaz80, (UBYTE *) "F10 : show this window", NULL }; struct IntuiText usage_text9 = { 2, 0, JAM1, 20, 125, &topaz80, (UBYTE *) "F9 : open NewCLI window" /* "F9 : open NewWSH window"*/, &usage_text10 }; struct IntuiText usage_text8 = { 2, 0, JAM1, 20, 115, &topaz80, (UBYTE *) "F8 : front screen to back", &usage_text9 }; struct IntuiText usage_text7 = { 2, 0, JAM1, 20, 105, &topaz80, (UBYTE *) "F7 : back screen to front", &usage_text8 }; struct IntuiText usage_text6 = { 2, 0, JAM1, 20, 95, &topaz80, (UBYTE *) "F6 : active window to back", &usage_text7 }; struct IntuiText usage_text5 = { 2, 0, JAM1, 20, 85, &topaz80, (UBYTE *) "F5 : active window to front", &usage_text6 }; struct IntuiText usage_text4 = { 2, 0, JAM1, 20, 75, &topaz80, (UBYTE *) "F4 : activate previous window", &usage_text5 }; struct IntuiText usage_text3 = { 2, 0, JAM1, 20, 65, &topaz80, (UBYTE *) "F3 : activate next window", &usage_text4 }; struct IntuiText usage_text2 = { 2, 0, JAM1, 20, 55, &topaz80, (UBYTE *) "F2 : front window to back", &usage_text3 }; struct IntuiText usage_text1 = { 2, 0, JAM1, 20, 45, &topaz80, (UBYTE *) "F1 : back window to front", &usage_text2 }; struct IntuiText title_text2 = { 3, 0, JAM1, WINDOW_WIDTH / 2 - 20 * 4, 30, &topaz80, (UBYTE *)"by Torsten Jürgeleit", &usage_text1 }; struct IntuiText title_text1 = { 0, 0, JAM1, WINDOW_WIDTH / 2 - 17 * 5, 18, &topaz60, (UBYTE *)"FKeys v1.1 03/89", &title_text2 }; struct NewWindow new_window = { 320 - WINDOW_WIDTH / 2, 100 - WINDOW_HEIGHT / 2, WINDOW_WIDTH, WINDOW_HEIGHT, 2, 3, GADGETUP, WINDOWDEPTH | WINDOWDRAG | ACTIVATE | SMART_REFRESH | RMBTRAP, NULL, NULL, (UBYTE *) " FKeys ", NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN }; /******/ BOOL remove_requester() { struct Window *window; struct IntuiMessage *msg; struct Gadget *gad; LONG class; BOOL remove = FALSE, exit = FALSE; if ((window = OpenWindow(&new_window)) == NULL) { DisplayBeep(NULL); remove = TRUE; } else { SetAPen(window->RPort, 1L); RectFill(window->RPort, 5L, 12L, WINDOW_WIDTH - 7L, WINDOW_HEIGHT - 4L); PrintIText(window->RPort, &title_text1, 0L, 0L); AddGList(window, &continue_gadget, -1L, -1L, NULL); RefreshGadgets(&continue_gadget, window, NULL); do { WaitPort(window->UserPort); while (msg = (struct IntuiMessage *)GetMsg(window->UserPort)) { class = msg->Class; gad = (struct Gadget *)msg->IAddress; ReplyMsg(msg); if (class == GADGETUP) { if (gad->GadgetID == GADGET_REMOVE) { remove = TRUE; } exit = TRUE; } } } while (exit == FALSE); CloseWindow(window); } return(remove); } /* Function table and functions for f1 to f10 */ VOID (*function_table[])() = { &back_window_to_front, /* f1 */ &front_window_to_back, /* f2 */ &activate_next_window, /* f3 */ &activate_previous_window, /* f4 */ &active_window_to_front, /* f5 */ &active_window_to_back, /* f6 */ &back_screen_to_front, /* f7 */ &front_screen_to_back, /* f8 */ &newcli, /* f9 */ &quit_program /* f10 */ }; VOID back_window_to_front() /* f1 */ { struct Window *window = bottom_window(IntuitionBase->ActiveScreen); if (window) { while (window && (window->Flags & BACKDROP)) { window = previous_window(window); /* skip backdrop windows */ } if (window) { WindowToFront(window); ActivateWindow(window); } } } VOID front_window_to_back() /* f2 */ { struct Window *window1 = top_window(IntuitionBase->ActiveScreen); struct Window *window2 = next_window(window1); if (window1) { WindowToBack(window1); if (window2) { ActivateWindow(window2); } } } VOID activate_next_window() /* f3 */ { struct Window *window = next_window(IntuitionBase->ActiveWindow); if (window) { ActivateWindow(window); } } VOID activate_previous_window() /* f4 */ { struct Window *window = previous_window(IntuitionBase->ActiveWindow); if (window == NULL) { window = bottom_window(IntuitionBase->ActiveScreen); } if (window) { ActivateWindow(window); } } VOID active_window_to_front() /* f5 */ { struct Window *window = IntuitionBase->ActiveWindow; if (window) { WindowToFront(window); } } VOID active_window_to_back() /* f6 */ { struct Window *window = IntuitionBase->ActiveWindow; if (window) { WindowToBack(window); } } VOID back_screen_to_front() /* f7 */ { struct Screen *screen = IntuitionBase->FirstScreen; struct Window *window; if (screen) { while (screen->NextScreen) { screen = screen->NextScreen; } ScreenToFront(screen); if (window = top_window(screen)) { ActivateWindow(window); } } } VOID front_screen_to_back() /* f8 */ { struct Screen *screen = IntuitionBase->FirstScreen; struct Window *window; if (screen) { ScreenToBack(screen); if (screen = IntuitionBase->FirstScreen) { if (window = top_window(screen)) { ActivateWindow(window); } } } } VOID newcli() /* f9 */ { action = ACTION_NEWCLI; Signal(main_task, SIGB_ACTION); /* send action signal to main task */ } VOID quit_program() /* f10 */ { action = ACTION_REMOVE_REQUESTER; Signal(main_task, SIGB_ACTION); /* send action signal to main task */ } /* Support routines for functions */ struct Window * top_window(screen) struct Screen *screen; { struct Window *window = NULL; struct Layer *layer = screen->LayerInfo.top_layer; while (layer && layer->Window == NULL) { layer = layer->back; } if (layer) { window = (struct Window *)layer->Window; } return(window); } struct Window * bottom_window(screen) struct Screen *screen; { struct Window *window = NULL; struct Layer *layer = screen->LayerInfo.top_layer; while (layer) { if (layer->Window) { window = (struct Window *)layer->Window; } layer = layer->back; } return(window); } struct Window * next_window(window) struct Window *window; { struct Layer *layer = window->WLayer; do { layer = layer->back; } while (layer && layer->Window == NULL); if (layer) { window = (struct Window *)layer->Window; } else { window = top_window(window->WScreen); } return(window); } struct Window * previous_window(window) struct Window *window; { struct Layer *layer = window->WLayer; do { layer = layer->front; } while (layer && layer->Window == NULL || layer->Window == window); if (layer) { window = (struct Window *)layer->Window; } else { window = NULL; } return(window); }