/* $Revision Header *** Header built automatically - do not edit! *********** * * (C) Copyright 1990 by MXM * * Name .....: MXMSub.c * Created ..: Saturday 06-Jan-90 23:30 * Revision .: 5 * * Date Author Comment * ========= ======== ==================== * 09-Mar-90 Olsen Rework for Aztec 5.0 * 14-Jan-90 Olsen Renamed to mxm.library * 07-Jan-90 Olsen Added InvertKeyMap * 07-Jan-90 Olsen - Empty log message - * 06-Jan-90 Olsen Created this file! * * $Revision Header ********************************************************/ #define REVISION 4 VOID CalcDimensions(cd_String,cd_Width,cd_Height,cd_MaxWidth) UBYTE *cd_String; LONG *cd_Width,*cd_Height,cd_MaxWidth; { LONG i,cd_InLine = 0,cd_NumLines = 0; *cd_Width = *cd_Height = 0; for(i = 0 ; i < strlen(cd_String) ; i++) { if(cd_String[i] == '\n' || cd_InLine == cd_MaxWidth) { if(cd_InLine > *cd_Width) *cd_Width = cd_InLine; cd_NumLines++; cd_InLine = 0; continue; } if(cd_String[i] == '\33') { while(cd_String[i] != 'm' && cd_String[i] != 'w' && i < strlen(cd_String)) i++; if(i >= strlen(cd_String)) i = strlen(cd_String) - 1; continue; } if(cd_String[i] < ' ') continue; cd_InLine++; } *cd_Height = cd_NumLines; if(cd_InLine > *cd_Width) *cd_Width = cd_InLine; } SHORT pop_computestate(); VOID pop_do_highlighting(); VOID pop_render(); VOID pop_draw_menuitem(); struct MenuItem *pop_getitem(); SHORT pop_strlen(); #define SETX 2 #define SETY 1 /* * pop_computestate() * * This function checks to see where the mouse pointer is in relation to * the various menu items in the menu. If it is inside one of them, it * returns which one (indexed by its linear position in the MenuItem list * with 0 being the first one). If not, returns -1. * * Possible future enhancement: keep a set of state variables containing * the UL and LR corners of the last-known select box; this would make * a quick check possible and would cut down the computation for short * mouse movements (the most common). */ SHORT pop_computestate(win, menu) struct Window *win; struct Menu *menu; { register SHORT current = 0; register SHORT xval, yval; register struct MenuItem *item; /* Get the x and y vals of the mouse position */ xval = win->MouseX - SETX; yval = win->MouseY - SETY; /* If there is a title, decrement the yval by the correct amount */ if(menu->MenuName) yval -= POPTITLEHEIGHT; /* First, see if the pointer is even in the window */ if((xval < 0) || (yval < 0) || (xval > win->Width - SETX) || (yval > win->Height - SETY)) return(-1); /* search through the list of menu items, checking the select box */ /* of each. If containment is detected, the job is done. */ item = menu->FirstItem; while(item) { if((xval >= item->LeftEdge) && (yval >= item->TopEdge) && (xval <= item->LeftEdge + item->Width) && (yval <= item->TopEdge + item->Height)) { /* We have found the quarry; now, the result only */ /* depends on the MenuItem's ITEMENABLED flag. */ if(item->Flags & ITEMENABLED) return(current); else return(-1); } current++; item = item->NextItem; } /* If the list is exhausted, return the sad news */ return(-1); } /* * pop_highlight() * * highlight a menu item */ #define pop_highlight(win, menu, state) pop_do_highlighting(win, menu, state, 0) /* * pop_unhighlight() * * unhighlight a menu item */ #define pop_unhighlight(win, menu, state) pop_do_highlighting(win, menu, state, 1) /* * pop_do_highlighting() * * Highlight or unhighlight a menu item, given its traversal number. Assumes * this is a rational value -- if it isn't, Watch Out. */ VOID pop_do_highlighting(win, menu, state, mode) struct Window *win; struct Menu *menu; SHORT state; SHORT mode; /* 0 means to highlight, 1 means to unhighlight */ { register struct MenuItem *item; struct RastPort *rp; SHORT offset = 0; if(menu->MenuName) offset = POPTITLEHEIGHT; /* Get the correct MenuItem structure */ item = pop_getitem(menu, state); rp = win->RPort; /* Now, do the highlighting! The action to be taken depends on */ /* the type of highlighting desired for this item. */ /* The way that the flags for highlighting works is truly bizarre */ if((item->Flags & HIGHNONE) == HIGHNONE) return; if(item->Flags & HIGHCOMP) { SetDrMd(rp, COMPLEMENT); RectFill(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge + offset + SETY), (LONG) (item->LeftEdge + item->Width - 1 + SETX), (LONG) (item->TopEdge + item->Height + offset + SETY)); } else if(item->Flags & HIGHBOX) { SetDrMd(rp, COMPLEMENT); Move(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge + offset + SETY)); Draw(rp, (LONG) (item->LeftEdge + item->Width - 1 + SETX), (LONG) (item->TopEdge + offset + SETY)); Draw(rp, (LONG) (item->LeftEdge + item->Width - 1 + SETX), (LONG) (item->TopEdge + item->Height + offset + SETY)); Move(rp, (LONG) (item->LeftEdge + item->Width - 2 + SETX), (LONG) (item->TopEdge + offset + 1 + SETY)); Draw(rp, (LONG) (item->LeftEdge + item->Width - 2 + SETX), (LONG) (item->TopEdge + item->Height + offset + SETY)); Draw(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge + item->Height + offset + SETY)); Draw(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge + offset + 1 + SETY)); Move(rp, (LONG) item->LeftEdge + 1 + SETX, (LONG) (item->TopEdge + offset + 1 + SETY)); Draw(rp, (LONG) item->LeftEdge + 1 + SETX, (LONG) (item->TopEdge + item->Height + offset - 1 + SETY)); } /* Otherwise, the mode is HIGHIMAGE */ else pop_draw_menuitem(win, item, !mode, offset); } /* * pop_render() * * renders the menu title (if existent) and the menu items */ VOID pop_render(win, menu) struct Window *win; struct Menu *menu; { struct MenuItem *item; struct RastPort *rp; SHORT offset = 0; rp = win->RPort; /* Fill the background with color 1, like Intuition Menus */ SetAPen(rp, 1L); RectFill(rp, 0L + SETX, 0L + SETY, (LONG) win->Width - SETX - 1, (LONG) win->Height - 2 - SETY); /* First, if there is a Title for this menu, render it in the top */ /* of the menu. */ if(menu->MenuName) { SetDrMd(rp, JAM1); SetAPen(rp, 1L); RectFill(rp, 0L, 0L, (LONG) win->Width - 1, (LONG) POPTITLEHEIGHT - 1); SetAPen(rp, 0L); SetBPen(rp, 1L); Move(rp, 4L + SETX, 7L); Text(rp, menu->MenuName, (LONG) pop_strlen(menu->MenuName)); SetDrMd(rp, COMPLEMENT); RectFill(rp, 0L, 0L, (LONG) win->Width - 1, (LONG) POPTITLEHEIGHT - 1); SetDrMd(rp, JAM1); offset = POPTITLEHEIGHT; SetAPen(rp, 0); Move(rp, 0, POPTITLEHEIGHT); Draw(rp, win->Width - 1, POPTITLEHEIGHT); } /* now render all of the menu items */ item = menu->FirstItem; while(item) { pop_draw_menuitem(win, item, 0, offset); item = item->NextItem; } } /* * pop_draw_menuitem() * * Draws the specified menuitem in the given rastport. The mode argument * says what to draw -- 0 means draw the ItemFill, 1 the SelectFill. */ VOID pop_draw_menuitem(win, item, mode, offset) struct Window *win; struct MenuItem *item; SHORT mode; SHORT offset; { /* Area fill patterns */ static USHORT pop_ghost_pattern[] = { 0x1111, 0x4444 }; static USHORT pop_normal_pattern[] = { 0xffff, 0xffff }; APTR fill; struct RastPort *rp; /* first, figure out what to do, and return if it is a NULL thing */ if(!mode) fill = item->ItemFill; else fill = item->SelectFill; if(!fill) return; rp = win->RPort; /* First, erase what may already be there, just to be sure that */ /* everything works out all right. */ SetAPen(rp, 1L); SetDrMd(rp, JAM1); RectFill(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge + offset + SETY), (LONG) (item->LeftEdge + item->Width + SETX - 1), (LONG) (item->TopEdge + item->Height + offset + SETY)); /* If the item is checkmarked, draw the checkmark. Intuition made */ /* sure that the CheckMark field of the window structure exists */ if(item->Flags & CHECKIT) if(item->Flags & CHECKED) DrawImage(rp, win->CheckMark, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge + offset + 1 + SETY)); /* Now, draw the item itself -- depending on the Flag value, it */ /* could be either an Image or an IntuiText */ if(item->Flags & ITEMTEXT) PrintIText(rp, fill, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge + offset + SETY)); else DrawImage(rp, fill, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge + offset + SETY)); /* If the ITEMENABLED flag is not set, "ghost" the item. */ if(!(item->Flags & ITEMENABLED)) { SetAPen(rp, 1L); SetDrMd(rp, JAM1); SetAfPt(rp, (USHORT *) pop_ghost_pattern, 1L); RectFill(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge + offset + SETY), (LONG) (item->LeftEdge + item->Width + SETX - 1), (LONG) (item->TopEdge + item->Height + offset + SETY)); SetAfPt(rp, (USHORT *) pop_normal_pattern, 1L); } } /* * pop_getitem() * * given the traversal number of a menu item in a menu (assumes, BTW, that * the arguments are valid), return a pointer to the MenuItem structure */ struct MenuItem * pop_getitem(menu, which) struct Menu *menu; SHORT which; { struct MenuItem *item; item = menu->FirstItem; while(which--) item = item->NextItem; return(item); } /* * pop_strlen() * * a home-brewed strlen to prevent it being necessary to hook in whatever * huge object file in which the c library's strlen() resides. */ SHORT pop_strlen(str) char *str; { register SHORT count = 0; for(; *str++; count++); return(count); } #define CONTROLBITS ( (1 << 5) | (1 << 6) ) ULONG InvertKeyMap(ansicode,ie,km) ULONG ansicode; register struct InputEvent *ie; struct KeyMap *km; { LONG kindex; UBYTE code = 0; ie -> ie_Class = IECLASS_RAWKEY; ie -> ie_EventAddress = 0; /* check for codes in (default) high map first */ switch(ansicode) { case ' ': code = 0x40; /* space */ break; case 0x08: code = 0x41; /* backspace */ break; case '\t': code = 0x42; /* tab */ break; case 0x0D: code = 0x44; /* return */ break; case 0x1B: code = 0x45; /* esc */ break; case 0x7F: code = 0x46; /* del */ break; } ie -> ie_Code = 0; ie -> ie_Qualifier = 0; if(code) { ie -> ie_Code = code; ie -> ie_Qualifier = 0; return(TRUE); } LowKeyInvert((UBYTE)ansicode,km,&ie -> ie_Code,&ie -> ie_Qualifier,&kindex); if(!ie -> ie_Code && !ie -> ie_Qualifier) return(FALSE); return(TRUE); } #define KEYMAPSIZE 64 /* LowKeyInvert returns good code else <0 if no find * * regarding keymap as many-to-one mapping: * -entries for a given key are scanned so that * the minimum number of qualifiers are associated * with the keystroke. * -passing a character value of zero corresponds, in * the default keymap, to CTRL-`, which is probably a bug. * -numerals are matched with numeric pad keystrokes (no * qualifiers) on standard keymap. The way to specify * a key on the number row is via its shifted value; * specify explicitly that the qualifier is to be unshifted, * or a "don't care." */ LowKeyInvert(value,km,codep,qualp,indexp) register UBYTE value; /* translation value from low keymap */ struct KeyMap *km; UWORD *codep; /* pointers where answers are to be put */ UWORD *qualp; ULONG *indexp; /* dead-key index information (put into ie?) */ { register UWORD code = KEYMAPSIZE - 1; /* last entry */ register unsigned int type; register LONG *p; /* points to four-byte lokeymap entry */ int found_it = 0; *indexp = *qualp = 0; p = (LONG *)km -> km_LoKeyMap + code; do { /* determine type of key */ if((type = km -> km_LoKeyMapTypes[code]) == KC_VANILLA) found_it = CheckVanilla(p,value,qualp); else if(!(type & KCF_NOP)) found_it = CheckNormal(p,value,type,qualp); --p; } while(!found_it && code--); *codep = code; return(code); } CheckNormal(four_bytesp, val, type, qualp) LONG four_bytesp; UBYTE val; UWORD type; UWORD *qualp; { register UBYTE *p = (UBYTE *)four_bytesp; /* codes held in long word */ register long position; /* start with last of four bytes, "more vanilla" */ p += 3; for(position = 3 ; position >= 0 ; --position, --p) { if(*p == val) { switch(type) { case KC_NOQUAL: if(position != 3) goto NOT_THIS; break; case KCF_SHIFT: if(!(position & 2)) goto NOT_THIS; if(position == 2) *qualp |= IEQUALIFIER_LSHIFT; break; case KCF_ALT: if(!(position & 2)) goto NOT_THIS; if(position == 2) *qualp |= IEQUALIFIER_LALT; break; case KCF_CONTROL: if(!(position & 2)) goto NOT_THIS; if(position == 2) *qualp |= IEQUALIFIER_CONTROL; break; case KCF_ALT | KCF_CONTROL: if(!(position & 1)) *qualp |= IEQUALIFIER_LALT; if(!(position & 2)) *qualp |= IEQUALIFIER_CONTROL; break; case KCF_SHIFT | KCF_CONTROL: if(!(position & 1)) *qualp |= IEQUALIFIER_LSHIFT; if(!(position & 2)) *qualp |= IEQUALIFIER_CONTROL; break; case KCF_SHIFT | KCF_ALT: if(!(position & 1)) *qualp |= IEQUALIFIER_LSHIFT; if(!(position & 2)) *qualp |= IEQUALIFIER_LALT; break; default: break; } return(TRUE); } NOT_THIS: ; } return(FALSE); } CheckVanilla(p,val,qualp) UBYTE *p; /* note: byte pointer */ UBYTE val; UWORD *qualp; { register int i; /* only one way to match a vanilla control key */ if(!(val & CONTROLBITS)) { /* is a control code */ if((p[3] & ~CONTROLBITS) == val) { *qualp |= IEQUALIFIER_CONTROL; return(TRUE); } } else { /* not a control */ for(i = 3 ; i >= 0 ; --i) { if(p[i] == val) { if(!(i & 1)) *qualp |= IEQUALIFIER_LSHIFT; if(!(i & 2)) *qualp |= IEQUALIFIER_LALT; return(TRUE); } } } return(FALSE); }