Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

cmd_user.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: cmd_user.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.28 $       $Date: 2019/01/17 21:21:03 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   Commands to allow the user to customize the hotkeys and pop-up menus.
00019  ***************************************************************************/
00020 
00021 #include <string.h>
00022 #include <ctype.h>  // for toupper/tolower
00023 #include <tcl.h>
00024 #include "config.h"
00025 #include "Mouse.h"
00026 #include "utilities.h"
00027 #include "DisplayDevice.h"
00028 #include "JString.h"
00029 #include "VMDApp.h"
00030 
00031 static int check_canonical_form(const char *s) {
00032   // Handle single-word key names
00033   if (!strcmp(s, "Escape")) return TRUE;
00034   if (!strcmp(s, "Up")) return TRUE;
00035   if (!strcmp(s, "Down")) return TRUE;
00036   if (!strcmp(s, "Left")) return TRUE;
00037   if (!strcmp(s, "Right")) return TRUE;
00038   if (!strcmp(s, "Page_Up")) return TRUE;
00039   if (!strcmp(s, "Page_Down")) return TRUE;
00040   if (!strcmp(s, "Home")) return TRUE;
00041   if (!strcmp(s, "End")) return TRUE;
00042   if (!strcmp(s, "Insert")) return TRUE;
00043   if (!strcmp(s, "Delete")) return TRUE;
00044 
00045   // Handle key code sequences involving combinations
00046   if (s[0] == 'A') {
00047     // could be a letter, 'Alt-', or 'Aux-'
00048     s++;
00049     if (*s == 0) {
00050       return TRUE;
00051     }
00052 
00053     // must be an Alt- or Aux-
00054     if (*s != 'l' && *s != 'u') {
00055       return FALSE;
00056     }
00057 
00058     if (*s == 'l') {
00059       s++;
00060       if (*s++ != 't') return FALSE;
00061       if (*s++ != '-') return FALSE;
00062     } else if (*s == 'u') {
00063       s++;
00064       if (*s++ != 'x') return FALSE;
00065       if (*s++ != '-') return FALSE;
00066     }
00067   }
00068 
00069   if (s[0] == 'C') {
00070     // could be a letter, or 'Control-'
00071     s++;
00072     if (*s == 0) {
00073       return TRUE;
00074     }
00075     // must be a Control
00076     if (*s++ != 'o') return FALSE;
00077     if (*s++ != 'n') return FALSE;
00078     if (*s++ != 't') return FALSE;
00079     if (*s++ != 'r') return FALSE;
00080     if (*s++ != 'o') return FALSE;
00081     if (*s++ != 'l') return FALSE;
00082     if (*s++ != '-') return FALSE;
00083   }
00084 
00085   if (s[0] == 'F') {
00086     // could be a letter, or 'Fn' (F1-F12)
00087     s++;
00088     if (*s == 0) {
00089       return TRUE;
00090     }
00091     // must be an Fn
00092     if ((*s) >= '0' && (*s) <= '9') {
00093       s++;
00094       if (*s == 0) {
00095         return TRUE;
00096       }
00097       if (*s >= '0' && *s <= '2') {
00098         s++;
00099         if (*s == 0) {
00100           return TRUE;
00101         }
00102       }
00103       return FALSE;
00104     }
00105   }
00106 
00107   // must be a single character
00108   if (s[0] == 0) return FALSE; // NULL, was invalid
00109 
00110   if (s[1] == 0) return TRUE; // was a valid single character
00111 
00112   return FALSE; // was otherwise invalid
00113 }
00114 
00115 int text_cmd_user(ClientData cd, Tcl_Interp *interp, int argc,
00116                             const char *argv[]) {
00117 
00118   VMDApp *app = (VMDApp *)cd;
00119 
00120   if(argc < 3) {
00121     Tcl_SetResult(interp, 
00122       (char *)
00123       "user list keys\n"
00124       "user print keys\n"
00125       "user add key <character> <command>",
00126       TCL_STATIC);
00127     return TCL_ERROR;
00128   }
00129 
00130   if(!strupncmp(argv[1], "add", CMDLEN)) {
00131     if (!strupncmp(argv[2], "key", CMDLEN)) {
00132       if(argc < 5)
00133         return TCL_ERROR;
00134       // check this is a valid string
00135       if (check_canonical_form(argv[3])) {
00136         const char *combstr = argv[4];
00137         const char *desc = NULL;
00138         if (argc > 5) desc = argv[5];
00139         int indx = app->userKeys.typecode(argv[3]);
00140         if (indx < 0) {
00141           app->userKeys.add_name(argv[3], stringdup(combstr));
00142         } else {
00143           delete [] app->userKeys.data(indx);
00144           app->userKeys.set_data(indx, stringdup(combstr));
00145         }
00146         if (desc) {
00147           indx = app->userKeyDesc.typecode(argv[3]);
00148           if (indx < 0) {
00149             app->userKeyDesc.add_name(argv[3], stringdup(desc));
00150           } else {
00151             delete [] app->userKeyDesc.data(indx);
00152             app->userKeys.set_data(indx, stringdup(desc));
00153           }
00154         }
00155       } else {
00156         Tcl_AppendResult(interp, "user key ", argv[3], " is not valid",
00157                          NULL);
00158         return TCL_ERROR;
00159       }
00160     }  else
00161       return TCL_ERROR;
00162 
00163   } else if(!strupncmp(argv[1], "list", CMDLEN)) {
00164     // return definitions of current items
00165     if (argc != 3) {
00166       return TCL_ERROR;
00167     }
00168     if (!strcmp(argv[2], "keys")) {
00169       int num = app->userKeys.num();
00170       for (int i=0; i<num; i++) {
00171         // return tuples of {keystroke command description}
00172         Tcl_AppendResult(interp, i==0?"":" ", "{", NULL);
00173         Tcl_AppendElement(interp,  app->userKeys.name(i));
00174         Tcl_AppendElement(interp, 
00175            (const char *) app->userKeys.data(i));
00176         int desc_typecode = app->userKeyDesc.typecode(app->userKeys.name(i));
00177         if (desc_typecode >= 0) {
00178           Tcl_AppendElement(interp,
00179              (const char *) app->userKeyDesc.data(i));
00180         } else {
00181           Tcl_AppendElement(interp, "");
00182         } 
00183         Tcl_AppendResult(interp, "}", NULL);
00184       }
00185       return TCL_OK;
00186     } else {
00187       return TCL_ERROR;
00188     }
00189     // will never get here
00190 
00191   } else if(!strupncmp(argv[1], "print", CMDLEN)) {
00192     // print out definitions of current items
00193     Tcl_AppendResult(interp, 
00194         "Keyboard shortcuts:\n",
00195         "-------------------\n", NULL);
00196     for (int i=0; i<app->userKeys.num(); i++) {
00197       const char *key = app->userKeys.name(i);
00198       Tcl_AppendResult(interp, "'", key, "' : ", app->userKeys.data(i), "\n",
00199           NULL);
00200       if (app->userKeyDesc.typecode(key) >= 0) {
00201         Tcl_AppendResult(interp, "     Description: ", 
00202             app->userKeyDesc.data(key), NULL);
00203       }
00204     }
00205   } else
00206     return TCL_ERROR;
00207     
00208   // if here, everything worked out ok
00209   return TCL_OK;
00210 }
00211 

Generated on Thu Mar 28 02:42:37 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002