/* * macros.c -- * * Defines and retrieves macros * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #ifndef lint static char rcsid[]="$Header: /ufs/repository/magic/macros/macros.c,v 1.6 2001/09/26 18:24:39 tim Exp $"; #endif #include #include #ifdef XLIB #include #include #include #endif #include "misc/magic.h" #include "utils/utils.h" #include "utils/malloc.h" #include "macros/macros.h" /* Define the start of the macro table */ macrodef *mactable = NULL; /*--------------------------------------------------------- * MacroDefine: * This procedure defines a macro. * * Results: None. * * Side Effects: * The string passed is copied and considered to be the * macro definition for the character. *--------------------------------------------------------- */ void MacroDefine(xc, str, imacro) int xc; /* full (X11) keycode of macro with modifiers */ char *str; /* ...and the string to be attached to it */ bool imacro; /* is this an interactive macro? */ { macrodef *newmacro, *cmacro; /* If a macro exists, delete the old string and redefine it */ for (cmacro = mactable; cmacro != NULL; cmacro = cmacro->nextmacro) { if (cmacro->keyvalue == xc) { newmacro = cmacro; break; } } if (cmacro == NULL) { MALLOC(macrodef *, newmacro, sizeof(macrodef)); newmacro->keyvalue = xc; newmacro->nextmacro = mactable; newmacro->macrodef = (char *)NULL; mactable = newmacro; } newmacro->interactive = imacro; newmacro->macrodef = StrDup(&(newmacro->macrodef), str); } /*--------------------------------------------------------- * MacroRetrieve: * This procedure retrieves a macro. * * Results: * A pointer to a new Malloc'ed string is returned. * This structure should be freed when the caller is * done with it. * * Side Effects: * None. *--------------------------------------------------------- */ char * MacroRetrieve(xc, iReturn) int xc; /* the extended name of the macro */ bool *iReturn; /* TRUE if macro is interactive */ { macrodef *cmacro; for (cmacro = mactable; cmacro != NULL; cmacro = cmacro->nextmacro) { if (cmacro->keyvalue == xc) { if (iReturn != NULL) *iReturn = cmacro->interactive; return ( StrDup( (char **) NULL, cmacro->macrodef) ); } } return (char *)NULL; } /*--------------------------------------------------------- * MacroDelete: * This procedure deletes a macro. * * Results: None. * * Side Effects: * The string that defines a macro is deleted. This means * that if anybody still has a pointer to that string * they are in trouble. *--------------------------------------------------------- */ void MacroDelete(xc) int xc; /* the extended name of the macro */ { macrodef *cmacro, *lmacro = NULL; for (cmacro = mactable; cmacro != NULL; cmacro = cmacro->nextmacro) { if (cmacro->keyvalue == xc) { if (lmacro != NULL) lmacro->nextmacro = cmacro->nextmacro; else mactable = cmacro->nextmacro; FREE(cmacro->macrodef); FREE(cmacro); break; } lmacro = cmacro; } } /* * ---------------------------------------------------------------------------- * MacroName -- * Convert an extended keycode to a string. * * Results: * The string. * * Side effects: * The string is malloc'ed from memory, and must be free'd later. * ---------------------------------------------------------------------------- */ char * MacroName(xc) int xc; { char *vis; static char hex[17] = "0123456789ABCDEF"; #ifdef XLIB char *str; extern Display *grXdpy; KeySym ks = xc & 0xffff; int kmod = xc >> 16; str = NULL; if (grXdpy != NULL) { ks = xc & 0xffff; if (ks != NoSymbol) str = XKeysymToString(ks); } if (str != NULL) { vis = (char *) mallocMagic( sizeof(char) * (strlen(str) + 32) ); vis[0] = '\0'; if (kmod & Mod1Mask) strcat(vis, "Meta_"); if (kmod & ControlMask) strcat(vis, "Control_"); if (kmod & LockMask) strcat(vis, "Capslock_"); if (kmod & ShiftMask) strcat(vis, "Shift_"); strcat(vis, "XK_"); strcat(vis, str); return (vis); } #endif vis = (char *) mallocMagic( sizeof(char) * 6 ); if (xc < (int)' ') { vis[0] = '^'; vis[1] = (char)xc + '@'; vis[2] = '\0'; } else if (xc == 0x7F) { vis[0] = '<'; vis[1] = 'd'; vis[2] = 'e'; vis[3] = 'l'; vis[4] = '>'; vis[5] = '\0'; } else if (xc < 0x80) { vis[0] = (char)xc; vis[1] = '\0'; } else { vis = (char *) mallocMagic( sizeof(char) * 8 ); vis[0] = '0'; vis[1] = 'x'; #ifdef XLIB vis[2] = hex[ (kmod & 0xf)]; #else vis[2] = '0'; #endif vis[3] = hex[ (xc & 0x0f000) >> 12]; vis[4] = hex[ (xc & 0x00f00) >> 8]; vis[5] = hex[ (xc & 0x000f0) >> 4]; vis[6] = hex[ (xc & 0x0000f) ]; vis[7] = '\0'; } return(vis); } /* * ---------------------------------------------------------------------------- * MacroKey: * Convert a string to an extended keycode. * * Results: * An extended macro name. * * Side effects: * If the display being used is not X11, a warning is printed the * first time this function is called. * ---------------------------------------------------------------------------- */ int MacroKey(str, verbose) char *str; int *verbose; { static int warn = 1; #ifdef XLIB int kc; char *vis; extern Display *grXdpy; KeySym ks; int kmod = 0; *verbose = 1; if (grXdpy != NULL) { vis = str; while( (*vis) != '\0' ) { if (!strncmp(vis, "Meta_", 5)) { kmod |= Mod1Mask; vis += 5; } else if (!strncmp(vis, "Alt_", 4)) { kmod |= Mod1Mask; vis += 4; } else if (!strncmp(vis, "Control_", 8)) { kmod |= ControlMask; vis += 8; } else if (((*vis) == '^') && (*(vis + 1) != '\0')) { kmod |= ControlMask; vis++; } else if (!strncmp(vis, "Capslock_", 9)) { kmod |= LockMask; vis += 9; } else if (!strncmp(vis, "Shift_", 6)) { kmod |= ShiftMask; vis += 6; } else break; } if (!strncmp(vis, "XK_", 3)) vis += 3; /* We're converting all ASCII back into X Keycodes */ /* The original macro (.magic) file format allows embedded */ /* control characters, so we have to handle those. For */ /* regular ASCII characters, the keysym = the ASCII value. */ if ((*(vis + 1)) == '\0') { /* single ASCII character handling */ char tc = *vis; /* Revert Control and Shift characters to ASCII */ /* unless other modifiers are present. Always make */ /* characters with Control and Shift uppercase. */ if (kmod & (ControlMask | ShiftMask)) { tc = toupper(tc); if (kmod & ShiftMask) kc = (int)tc; else if (kmod & ControlMask) kc = (int)(tc - 'A' + 1); if (!(kmod & (Mod1Mask | LockMask))) if (!(kmod & ShiftMask) || !(kmod & ControlMask)) kmod = 0; } else kc = (int)tc; } else { /* X11 keysym name handling */ ks = XStringToKeysym(vis); kc = (ks != NoSymbol) ? ks & 0xffff : 0; } return (kc | (kmod << 16)); } #endif *verbose = 1; if (strlen(str) == 1) { return (int)str[0]; } else if (strlen(str) == 2 && *str == '^') { return (int)str[1] - 'A' + 1; } if (warn) TxError("Extended macros are unavailable with this device type.\n"); warn = 0; *verbose = 0; return(0); } /* * ---------------------------------------------------------------------------- * CommandLineTranslate * Convert X11 definitions to readline controls * * Results: * A converted character (integer) * * Side effects: * None. * ---------------------------------------------------------------------------- */ int TranslateChar(key) int key; { int rval = key; #ifdef XLIB switch (key) { case XK_Left: rval = (int)'\002'; /* Ctrl-B */ break; case XK_Right: rval = (int)'\006'; /* Ctrl-F */ break; case XK_Up: rval = (int)'\020'; /* Ctrl-P */ break; case XK_Down: rval = (int)'\016'; /* Ctrl-N */ break; case XK_BackSpace: case XK_Delete: rval = (int)'\010'; /* Ctrl-H */ break; case XK_Home: rval = (int)'\001'; /* Ctrl-A */ break; case XK_End: rval = (int)'\005'; /* Ctrl-E */ break; } #endif return rval; }