Re: How can I open file in exist window?
Fabrice Popineau <[email protected]>
| Newsgroups | gmane.emacs.xemacs.windows,gmane.emacs.xemacs.beta |
|---|---|
| Message-ID | <[email protected]> |
> I'd like that starting XEmacs-NT [version 21.4; April 2001] as xemacs > +100 foo.tex > should open foo.txt at line 100 with launched instance of XEmacs, > rather than start another one. > The program `winclient.exe' does not meet my needs, becase it does not > recognize the option `+number-line'. Juste because the most recent work from Alastair J. Houghton has not been integrated into the main source tree. Try the files attached. It will work the way you want. -- Fabrice
winclient.c
(application/octet-stream, 9.2 KB)
/* DDE client for XEmacs.
Copyright (C) 2002 Alastair J. Houghton
This file is part of XEmacs.
XEmacs 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.
XEmacs 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 XEmacs; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Synched up with: Not in FSF. */
#include <windows.h>
#include <ddeml.h>
#include <dde.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#define XEMACS_EXE "xemacs.exe"
#define XEMACS "XEmacs"
#define EVAL_TOPIC "Eval"
#define RESULT_ITEM "Result"
#define ERROR_ITEM "Error"
/* Timeouts & delays */
#define CONNECT_DELAY 500 /* ms */
#define TRANSACTION_TIMEOUT 5000 /* ms */
#define MAX_INPUT_IDLE_WAIT INFINITE /* ms */
static DWORD DDEsession;
static HCONV DDEconversation;
void CloseConversation (void)
{
if (DDEconversation)
DdeDisconnect(DDEconversation);
if (DDEsession)
DdeUninitialize(DDEsession);
}
void error(LPCTSTR fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fputc('\n', stderr);
/* Tidy up */
CloseConversation();
exit(1);
}
void *emalloc(size_t len)
{
void *p = malloc(len);
if (p == NULL)
error("Out of memory - cannot allocate %d bytes", len);
return p;
}
int outstanding_requests;
HDDEDATA CALLBACK
Callback (UINT uType, UINT uFmt, HCONV hconv, HSZ hsz1, HSZ hsz2,
HDDEDATA hdata, DWORD dwData1, DWORD dwData2)
{
#ifndef WINDOIT
if (uType == XTYP_ADVDATA)
{
DWORD len = DdeGetData(hdata, NULL, 0, 0);
char *buf = _alloca(len + 1);
DdeGetData(hdata, (LPBYTE)buf, len + 1, 0);
if (--outstanding_requests == 0)
PostQuitMessage(0);
return (HDDEDATA) DDE_FACK;
}
#endif
return (HDDEDATA) NULL;
}
int StartServer(LPCTSTR prog)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
int n;
ZeroMemory (&si, sizeof (si));
si.cb = sizeof (si);
if (!CreateProcess (NULL, (LPTSTR)prog, NULL, NULL, FALSE, 0,
NULL, NULL, &si, &pi))
{
error("Could not start process %s", prog);
return 1;
}
/* Wait for the process to enter an idle state */
WaitForInputIdle (pi.hProcess, MAX_INPUT_IDLE_WAIT);
/* Close the handles */
CloseHandle (pi.hThread);
CloseHandle (pi.hProcess);
return 0;
}
HSZ DDEString(LPCTSTR str)
{
HSZ hsz = DdeCreateStringHandle(DDEsession, str, CP_WINANSI);
if (hsz == 0)
error("Cannot create string for %s", str);
return hsz;
}
FreeString(HSZ hsz)
{
DdeFreeStringHandle(DDEsession, hsz);
}
void OpenConversation(LPCTSTR topic_name)
{
UINT ret;
HSZ service;
HSZ topic;
int n;
ret = DdeInitialize(&DDEsession, Callback, APPCMD_CLIENTONLY, 0);
if (ret != DMLERR_NO_ERROR)
error("Cannot start DDE");
service = DDEString(XEMACS);
topic = DDEString(topic_name);
DDEconversation = DdeConnect(DDEsession, service, topic, 0);
if (DDEconversation == 0)
{
if (StartServer(XEMACS_EXE) == 0)
{
/* Try to connect */
for (n = 0; n < 5; n++)
{
Sleep (CONNECT_DELAY);
DDEconversation = DdeConnect(DDEsession, service, topic, 0);
if (DDEconversation)
break;
}
if (DDEconversation == 0)
error("Cannot contact server %s", XEMACS);
}
}
FreeString(service);
FreeString(topic);
}
void ExecuteCommand(LPCTSTR command)
{
HDDEDATA ret;
ret = DdeClientTransaction((LPBYTE)command, strlen(command) + 1,
DDEconversation, 0, 0, XTYP_EXECUTE,
TRANSACTION_TIMEOUT, 0);
if (ret == 0)
error("Cannot execute command \"%s\"", command);
}
void StartHotLink(LPCTSTR item_name)
{
HSZ item = DDEString(item_name);
DdeClientTransaction(0, 0, DDEconversation, item, CF_TEXT, XTYP_ADVSTART,
TRANSACTION_TIMEOUT, 0);
FreeString(item);
}
LPTSTR RequestData (LPCTSTR item_name)
{
HSZ item = DDEString(item_name);
DWORD len;
char *buf;
HDDEDATA result;
result = DdeClientTransaction (NULL, 0, DDEconversation, item, CF_TEXT,
XTYP_REQUEST, TRANSACTION_TIMEOUT, 0);
FreeString(item);
if (result == 0)
error("Cannot request item %s\n", item_name);
len = DdeGetData(result, NULL, 0, 0);
buf = emalloc(len + 1);
DdeGetData(result, (LPBYTE)buf, len + 1, 0);
return buf;
}
void pump_messages()
{
MSG msg;
HWND hwnd;
BOOL ret;
while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (ret != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
LPCTSTR EvaluateCommand(LPCTSTR forms)
{
int i;
LPTSTR result;
ExecuteCommand(forms);
result = RequestData(RESULT_ITEM);
/* Status is "OK: xxx" or "ERR: xxx" */
if (strncmp(result, "ERR:", 4) == 0)
error("%s\n", result + 5);
/* Move the result down */
for (i = 4; result[i]; ++i)
result[i-4] = result[i];
result[i-4] = 0;
return result;
}
LPCTSTR BuildForm(LPCTSTR command, LPCTSTR path)
{
/* Format is (command "path"), where backslashes and quotes in path
* must be backslash-escaped. So we need a buffer of size command length
* plus 2 * path length plus 6 (quotes, parens, space, and terminating 0).
*/
size_t buflen = strlen(command) + 2 * strlen(path) + 6;
LPTSTR buf = emalloc(buflen);
LPCTSTR src;
LPTSTR dest = buf;
*dest++ = '(';
strcpy(dest, command);
dest += strlen(command);
*dest++ = ' ';
*dest++ = '"';
for (src = path; *src; ++src)
{
if (*src == '\\' || *src == '"')
*dest++ = '\\';
*dest++ = *src;
}
*dest++ = '"';
*dest++ = ')';
*dest = 0;
return buf;
}
void LoadFile(LPCTSTR command, LPCTSTR file, int line, LPCTSTR *result)
{
LPTSTR filepart;
LPCTSTR form;
TCHAR path[MAX_PATH];
if (GetFullPathName(file, MAX_PATH, path, &filepart) == 0)
error("Cannot get path for %s", file);
form = BuildForm(command, path);
if (result)
*result = EvaluateCommand(form);
else
ExecuteCommand(form);
free((void *)form);
if (line >= 0)
{
char buf[50];
sprintf(buf, "(goto-line %d)", line);
ExecuteCommand(buf);
}
}
void do_files (int argc, LPCTSTR argv[], int wait)
{
int i;
LPCTSTR cmd;
LPCTSTR result;
OpenConversation(EVAL_TOPIC);
if (wait)
{
cmd = "request-edit";
ExecuteCommand("(require 'dde)");
outstanding_requests = 0;
}
else
{
cmd = "find-file";
}
for (; argc; ++argv, --argc)
{
int line = -1;
if (argc > 1 && *argv[0] == '+')
{
line = atoi(argv[0]);
++argv;
--argc;
}
LoadFile(cmd, *argv, line, (wait ? &result : 0));
ExecuteCommand("(raise-frame)");
if (wait)
{
++outstanding_requests;
StartHotLink(result);
free((void *)result);
}
}
if (wait)
{
/* Wait for completion notifications... */
pump_messages();
}
CloseConversation();
}
void usage()
{
printf("Usage:\n");
#ifdef WINDOIT
printf("windoit [-q] form...\n");
printf(" Evaluate forms (-q means do not wait for a result)\n");
#else
printf("winclient [-w] file...\n");
printf(" Load files (-w means wait for the user to finish)\n");
#endif
}
#ifdef WINDOIT
void SkipProgramName (LPTSTR *cmdline)
{
int in_quote = 0;
LPTSTR cmd = *cmdline;
while (*cmd)
{
if (!in_quote && isspace(*cmd))
break;
if (*cmd == '"')
in_quote = !in_quote;
/* Backslash protects quotes
* so they don't count for protecting spaces
*/
if (*cmd == '\\')
++cmd;
++cmd;
}
while (*cmd && isspace(*cmd))
++cmd;
*cmdline = cmd;
}
void TrimTrailingSpace (LPTSTR cmdline)
{
size_t len = strlen(cmdline);
while (len > 0 && isspace(cmdline[len-1]))
--len;
cmdline[len] = '\0';
}
int CheckOption(LPTSTR *cmdline, TCHAR option)
{
LPTSTR cmd = *cmdline;
if (cmd[0] == '-' && cmd[1] == option
&& (cmd[2] == '\0' || isspace(cmd[2])))
{
cmd += 2;
while (*cmd && isspace(*cmd))
++cmd;
*cmdline = cmd;
return 1;
}
return 0;
}
int main ()
{
LPTSTR cmdline = GetCommandLine();
int quiet = 0;
SkipProgramName(&cmdline);
TrimTrailingSpace(cmdline);
if (*cmdline == 0 || CheckOption(&cmdline, '?'))
{
usage();
return 0;
}
if (CheckOption(&cmdline, 'q'))
quiet = 1;
OpenConversation(EVAL_TOPIC);
if (quiet)
ExecuteCommand(cmdline);
else
{
LPCTSTR result = EvaluateCommand(cmdline);
printf("%s\n", result);
free((void *)result);
}
CloseConversation();
return 0;
}
#else
int main (int argc, const char *argv[])
{
int i;
int wait = 0;
/* Skip the program name */
++argv;
--argc;
if (argc == 0 || strcmp(argv[0], "-?") == 0)
{
usage();
return 0;
}
if (strcmp(argv[0], "-w") == 0)
{
wait = 1;
++argv;
--argc;
}
do_files(argc, argv, wait);
return 0;
}
#endif
dde.el
(application/emacs-lisp, 440 B) - not displayed