/* Add entries to the GNU Emacs Program Manager folder. Copyright (C) 1995 Free Software Foundation, Inc. This file is currently NOT part of GNU Emacs. GNU Emacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /**************************************************************************** * * Program: usethis * Adds emacs_dir to registry for gnuclient[w]. * Uses HKLM if possible and HKCU is not already used. * * Heavily based on addpm.c in GNU Emacs. * Author: Lennart Borgman * * Usage: (see print_usage_exit) */ #include //#include #include #include #include #include "getopt.h" #ifndef X_OK /* Some defines for _access nAccessMode (MS doesn't define them, but * it doesn't seem to hurt to add them). */ #define F_OK 0 /* Check for file existence */ #define X_OK 1 /* Check for execute permission. */ #define W_OK 2 /* Check for write permission */ #define R_OK 4 /* Check for read permission */ #endif /* HDDEDATA CALLBACK DdeCallback (UINT uType, UINT uFmt, HCONV hconv, HSZ hsz1, HSZ hsz2, HDDEDATA hdata, DWORD dwData1, DWORD dwData2) { return ((HDDEDATA) NULL); } #define DdeCommand(str) \ DdeClientTransaction (str, strlen (str)+1, HConversation, (HSZ)NULL, \ CF_TEXT, XTYP_EXECUTE, 30000, NULL) */ #define REG_ROOT "SOFTWARE\\GNU\\Emacs" static struct entry { char *name; char *value; } env_vars[] = { {"emacs_dir", NULL}, }; #define ADDREG_FAILURE 0 #define ADDREG_DONE_USER1 1 #define ADDREG_DONE_USER2 2 #define ADDREG_DONE_USER3 3 #define ADDREG_DONE_MACHINE 4 int uflg = 0; /* Set only for current user? */ int qflg = 0; int add_registry (path) char *path; { HKEY hrootkey = NULL; DWORD dwDisp; int i; int result = ADDREG_FAILURE; DWORD temp_data_type = (DWORD) REG_SZ; CHAR temp_string[ 2048 ]; int size_of_buffer = 2048; LONG ErrorCode; int uflg_given = uflg; memset( temp_string, 0, sizeof( temp_string ) ); /* First see if key for emacs_dir exists in HKCU, then HKCU must be used */ if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS) { if (0 == uflg) { ErrorCode = RegQueryValueEx( hrootkey, "emacs_dir", NULL, &temp_data_type, temp_string, &size_of_buffer ); if (ErrorCode == ERROR_SUCCESS ) { uflg++; } } } if (uflg) { if (RegCreateKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hrootkey, &dwDisp) != ERROR_SUCCESS) { RegCloseKey (hrootkey); return result; } if (uflg_given) { result = ADDREG_DONE_USER3; } else { result = ADDREG_DONE_USER1; } } if (result == ADDREG_FAILURE) { /* Check both the current user and the local machine to see if we have any resources. */ if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hrootkey, &dwDisp) == ERROR_SUCCESS) { result = ADDREG_DONE_MACHINE; } else { if (RegCreateKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hrootkey, &dwDisp) != ERROR_SUCCESS) { return result; } result = ADDREG_DONE_USER2; } } /* A bit too complex now, but it works! */ for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++) { char * value = env_vars[i].value ? env_vars[i].value : path; if (RegSetValueEx (hrootkey, env_vars[i].name, 0, REG_EXPAND_SZ, value, lstrlen (value) + 1) != ERROR_SUCCESS) result = ADDREG_FAILURE; } RegCloseKey (hrootkey); return (result); } //#include "redirerr.h" static int old_handle = -1; char *title = "Setup gnuclient[w] for Emacs - usethis V0.91"; void tell_int(char *sMsg, BOOL bErr, BOOL bForceMsgBox) { char msgbuf[2048]; int msgflg = MB_OK | MB_ICONINFORMATION; strcpy(msgbuf, ""); if (bErr) { strcpy(msgbuf, "\n** ERROR **\n"); } strcat(msgbuf, sMsg); if (bErr) { fprintf (stderr, msgbuf); fflush(stderr); msgflg = MB_OK | MB_ICONERROR; qflg = 0; } else { fprintf (stdout, msgbuf); fflush(stdout); } if (!qflg) MessageBox (NULL, msgbuf, title, msgflg); } // tell_user void tell_user(char *sMsg) { tell_int(sMsg, FALSE, FALSE); } void tell_err(char *sErrMsg) { tell_int(sErrMsg, TRUE, TRUE); } void tell_err_exit(char *sErrMsg) { tell_err(sErrMsg); exit(1); } void print_usage_exit() { char *sUsage = "Usage: usethis [-h] | [-q] [-u] [-d emacs_dir]\n" "\n" " Options:\n" " -h \t\tPrint usage message\n" " -q \t\tQuiet (no message box)\n" " -u \t\tSet only for current user\n" " -d emacs_dir \tFull path to Emacs bin dir parent dir\n" "\n" " Without -d usethis.exe's parent directory is used for EMACS_DIR.\n" ; tell_int(sUsage, FALSE, TRUE); exit(0); } // print_usage_exit int main (argc, argv) int argc; char *argv[]; { int cc; /* char from getopt */ DWORD idDde = 0; //HCONV HConversation; //HSZ ProgMan; char modname[MAX_PATH]; //char additem[MAX_PATH*2 + 100]; //char *prog_name; char *emacs_dir; char runemacs_exe[MAX_PATH]; char *p; int addres; int dflg = 0; char stderr_buf[2048]; //char stderr_file[MAX_PATH]; /* Redirect stderr to get error messages from getopt */ //mk_full_temp_file_name("gnuserv_useit_stderr.tmp", stderr_file); //old_handle = do_redir_stderr(stderr_file); strcpy(stderr_buf, ""); while ((cc = getopt_win(argc, argv, "d:h?qu", stderr_buf)) != EOF) { switch (cc) { case 'd': /* path to emacs binaries */ dflg++; emacs_dir = optarg; break; case 'u': /* set for current user only */ uflg++; break; case 'q': /* quite mode specified */ qflg = 1; break; case 'h': /* help required */ print_usage_exit(); case '?': break; //-- used by getopt default: tell_err_exit("Internal error in getopt use"); }; /* switch */ } /* Check getopt errors: */ //undo_redir_stderr(old_handle, stderr_file, stderr_buf); if (strlen(stderr_buf) > 0 ) { strcat(stderr_buf, "\n\nUse -h for help.\n"); tell_err_exit(stderr_buf); } if (!dflg) { /* Find out this exe files path */ if (!GetModuleFileName (NULL, modname, MAX_PATH) || (p = strrchr (modname, '\\')) == NULL) { tell_err_exit("Fatal error, could not get module name.\n"); } *p = 0; /* Set emacs_dir if we are in what is going to be "%emacs_dir%\bin". */ if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0) { *p = 0; emacs_dir = modname; } else { tell_err_exit("usethis.exe must be in Emacs bin dir if not -d is used.\n"); } } /* Check emacs_dir. */ if (access(emacs_dir, X_OK) != 0) { char errbuf[1024]; sprintf(errbuf, "Can't find directory %s\n", emacs_dir); tell_err_exit(errbuf); } /* Maybe fix: Check that emacs_dir is a directory? */ /* Check we know where [run]emacs.exe is. */ strcpy(runemacs_exe, emacs_dir); /* Will runemacs be there? Use emacs.exe instead. */ strcat(runemacs_exe, "\\bin\\emacs.exe"); if (access(runemacs_exe, X_OK) != 0) { char errbuf[1024]; sprintf(errbuf, "Can't find emacs.exe in %s\\bin\n", emacs_dir); tell_err_exit(errbuf); } /* Tell user what we are going to do. */ if (!qflg) { int result; char msg[ MAX_PATH ]; sprintf (msg, "Setup gnuclient[w] to use Emacs at %s?\n", emacs_dir); result = MessageBox (NULL, msg, title, MB_OKCANCEL | MB_ICONQUESTION); if (result != IDOK) { result = MessageBox(NULL, "Cancelled by user\n", title, MB_ICONWARNING); exit(1); } } /* Add emacs_dir to registry */ addres = add_registry (emacs_dir); switch(addres) { case ADDREG_FAILURE: tell_err_exit("Failed to setup gnuclient - ADDREG_FAILURE"); break; case ADDREG_DONE_USER1: tell_user("Done for current user only (because key already exists in HKCU " "- new value will not be used if written to HKLM)."); break; case ADDREG_DONE_USER2: tell_user("Done for current user only (no priv to reg for all users)."); break; case ADDREG_DONE_USER3: tell_user("Done for current user."); break; case ADDREG_DONE_MACHINE: tell_user("Done for all users."); break; default: tell_err_exit("Internal error - coult not add to registry"); } /* - Lennart Borgman 2004-10-19: Commented out creation of PROGMAN link to runemacs.exe, since this is normally not the way you want to start Emacs. It should be started with gnuclientw.exe (or emacsclient when that is available). Adding of shortcuts is now instead done by Emacs Setup Utilities for MS Windows. prog_name = "runemacs.exe"; DdeInitialize (&idDde, (PFNCALLBACK)DdeCallback, APPCMD_CLIENTONLY, 0); ProgMan = DdeCreateStringHandle (idDde, "PROGMAN", CP_WINANSI); HConversation = DdeConnect (idDde, ProgMan, ProgMan, NULL); if (HConversation != 0) { DdeCommand ("[CreateGroup (\"Gnu Emacs\")]"); DdeCommand ("[ReplaceItem (Emacs)]"); if (argc > 2) sprintf (additem, "[AddItem (\"%s\\bin\\%s\", Emacs, \"%s\")]", emacs_dir, prog_name, argv[2]); else sprintf (additem, "[AddItem (\"%s\\bin\\%s\", Emacs)]", emacs_dir, prog_name); DdeCommand (additem); DdeDisconnect (HConversation); } DdeFreeStringHandle (idDde, ProgMan); DdeUninitialize (idDde); */ return (0); }