To: vim-dev@vim.org Subject: Patch 6.0.162 (extra) Fcc: outbox From: Bram Moolenaar MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 6.0.162 Problem: Client-server: An error message for a wrong expression appears in the server instead of the cient. Solution: Pass the error message from the server to the client. Also adjust the example code. (Flemming Madsen) Files: src/globals.h, src/if_xcmdsrv.c, src/main.c, src/os_mswin.c, src/proto/if_xcmdsrv.pro, src/proto/os_mswin.pro, runtime/doc/eval.txt, runtime/tools/xcmdsrv_client.c *** ../vim60.161/src/globals.h Fri Nov 2 16:29:44 2001 --- src/globals.h Sun Feb 3 11:57:48 2002 *************** *** 1132,1137 **** --- 1133,1141 ---- EXTERN char_u e_zerocount[] INIT(=N_("Zero count")); #ifdef FEAT_EVAL EXTERN char_u e_usingsid[] INIT(=N_("E81: Using not in a script context")); + #endif + #ifdef FEAT_CLIENTSERVER + EXTERN char_u e_invexprmsg[] INIT(=N_("E449: Invalid expression received")); #endif /* *** ../vim60.161/src/if_xcmdsrv.c Sat Nov 3 14:16:30 2001 --- src/if_xcmdsrv.c Sun Feb 3 12:18:33 2002 *************** *** 70,75 **** --- 70,76 ---- typedef struct PendingCommand { int serial; /* Serial number expected in result. */ + int code; /* Result Code. 0 is OK */ char_u *result; /* String result for command (malloc'ed). * NULL means command still pending. */ struct PendingCommand *nextPtr; *************** *** 136,141 **** --- 137,145 ---- * defaults to an empty string. * * -c code + * 0: for OK. This is the default. + * 1: for error: Result is the last error + * * -i errorInfo * -e errorCode * Not applicable for Vim *************** *** 385,393 **** ret = eval_to_string(cmd, NULL); --emsg_skip; if (result != NULL) ! *result = ret; else vim_free(ret); } else server_to_input_buf(cmd); --- 389,403 ---- ret = eval_to_string(cmd, NULL); --emsg_skip; if (result != NULL) ! { ! if (ret == NULL) ! *result = vim_strsave(_(e_invexprmsg)); ! else ! *result = ret; ! } else vim_free(ret); + return ret == NULL ? -1 : 0; } else server_to_input_buf(cmd); *************** *** 461,466 **** --- 471,477 ---- * AppendErrorProc to pass back the command's results). */ pending.serial = serial; + pending.code = 0; pending.result = NULL; pending.nextPtr = pendingCommands; pendingCommands = &pending; *************** *** 489,495 **** else vim_free(pending.result); ! return 0; } static int --- 500,506 ---- else vim_free(pending.result); ! return pending.code == 0 ? 0 : -1; } static int *************** *** 1092,1098 **** { char_u *propInfo; char_u *p; ! int result, actualFormat; long_u numItems, bytesAfter; Atom actualType; --- 1103,1109 ---- { char_u *propInfo; char_u *p; ! int result, actualFormat, code; long_u numItems, bytesAfter; Atom actualType; *************** *** 1223,1228 **** --- 1234,1245 ---- { if (res != NULL) ga_concat(&reply, res); + else if (asKeys == 0) + { + ga_concat(&reply, _(e_invexprmsg)); + ga_append(&reply, 0); + ga_concat(&reply, "-c 1"); + } ga_append(&reply, 0); (void)AppendPropCarefully(dpy, resWindow, commProperty, reply.ga_data, reply.ga_len); *************** *** 1243,1248 **** --- 1260,1266 ---- p += 2; gotSerial = 0; res = (char_u *)""; + code = 0; while ((p-propInfo) < numItems && *p == '-') { switch (p[1]) *************** *** 1255,1260 **** --- 1273,1282 ---- if (sscanf((char *)p + 2, " %d", &serial) == 1) gotSerial = 1; break; + case 'c': + if (sscanf((char *)p + 2, " %d", &code) != 1) + code = 0; + break; } while (*p != 0) p++; *************** *** 1273,1278 **** --- 1295,1301 ---- if (serial != pcPtr->serial || pcPtr->result != NULL) continue; + pcPtr->code = code; if (res != NULL) pcPtr->result = vim_strsave(res); else *** ../vim60.161/src/main.c Mon Nov 5 22:06:57 2001 --- src/main.c Sun Feb 3 11:45:33 2002 *************** *** 2628,2634 **** while (memchr(done, 0, numFiles) != NULL) { # ifdef WIN32 ! p = serverGetReply(srv, FALSE, TRUE, TRUE); if (p == NULL) break; # else --- 2628,2634 ---- while (memchr(done, 0, numFiles) != NULL) { # ifdef WIN32 ! p = serverGetReply(srv, NULL, TRUE, TRUE); if (p == NULL) break; # else *** ../vim60.161/src/os_mswin.c Sun Dec 30 21:52:17 2001 --- src/os_mswin.c Sun Feb 3 11:57:57 2002 *************** *** 1716,1725 **** /* Communication is via WM_COPYDATA messages. The message type is send in * the dwData parameter. Types are defined here. */ ! #define COPYDATA_KEYS 0 ! #define COPYDATA_REPLY 1 ! #define COPYDATA_EXPR 10 ! #define COPYDATA_RESULT 11 /* This is a structure containing a server HWND and its name. */ struct server_id --- 1716,1726 ---- /* Communication is via WM_COPYDATA messages. The message type is send in * the dwData parameter. Types are defined here. */ ! #define COPYDATA_KEYS 0 ! #define COPYDATA_REPLY 1 ! #define COPYDATA_EXPR 10 ! #define COPYDATA_RESULT 11 ! #define COPYDATA_ERROR_RESULT 12 /* This is a structure containing a server HWND and its name. */ struct server_id *************** *** 1775,1780 **** --- 1776,1784 ---- * COPYDATA_RESULT: * A reply. We are a client, and a server has sent this message * in response to a COPYDATA_EXPR. + * COPYDATA_ERROR_RESULT: + * A reply. We are a client, and a server has sent this message + * in response to a COPYDATA_EXPR that failed to evaluate. */ COPYDATASTRUCT *data = (COPYDATASTRUCT*)lParam; HWND sender = (HWND)wParam; *************** *** 1808,1815 **** res = eval_to_string(data->lpData, NULL); --emsg_skip; if (res == NULL) ! res = vim_strsave((char_u *)""); ! reply.dwData = COPYDATA_RESULT; reply.lpData = res; reply.cbData = STRLEN(res) + 1; --- 1812,1823 ---- res = eval_to_string(data->lpData, NULL); --emsg_skip; if (res == NULL) ! { ! res = vim_strsave(_(e_invexprmsg)); ! reply.dwData = COPYDATA_ERROR_RESULT; ! } ! else ! reply.dwData = COPYDATA_RESULT; reply.lpData = res; reply.cbData = STRLEN(res) + 1; *************** *** 1820,1829 **** case COPYDATA_REPLY: case COPYDATA_RESULT: if (data->lpData != NULL) { save_reply(sender, data->lpData, ! data->dwData == COPYDATA_RESULT); #ifdef FEAT_AUTOCMD if (data->dwData == COPYDATA_REPLY) { --- 1828,1840 ---- case COPYDATA_REPLY: case COPYDATA_RESULT: + case COPYDATA_ERROR_RESULT: if (data->lpData != NULL) { save_reply(sender, data->lpData, ! (data->dwData == COPYDATA_REPLY ? 0 : ! (data->dwData == COPYDATA_RESULT ? 1 : ! 2))); #ifdef FEAT_AUTOCMD if (data->dwData == COPYDATA_REPLY) { *************** *** 2071,2076 **** --- 2082,2088 ---- HWND target = findServer(name); COPYDATASTRUCT data; char_u *retval = NULL; + int retcode = 0; if (ptarget) *(HWND *)ptarget = target; *************** *** 2084,2097 **** return -1; if (asExpr) ! retval = serverGetReply(target, TRUE, TRUE, TRUE); if (result == NULL) vim_free(retval); else *result = retval; /* Caller assumes responsibility for freeing */ ! return 0; } /* --- 2096,2109 ---- return -1; if (asExpr) ! retval = serverGetReply(target, &retcode, TRUE, TRUE); if (result == NULL) vim_free(retval); else *result = retval; /* Caller assumes responsibility for freeing */ ! return retcode; } /* *************** *** 2119,2125 **** { HWND server; /* server window */ char_u *reply; /* reply string */ ! int expr_result; /* TRUE for COPYDATA_RESULT */ } reply_T; --- 2131,2137 ---- { HWND server; /* server window */ char_u *reply; /* reply string */ ! int expr_result; /* 0 for REPLY, 1 for RESULT 2 for error */ } reply_T; *************** *** 2155,2167 **** /* * Get a reply from server "server". ! * When "expr" is TRUE, get the result of an expression, otherwise a * server2client() message. * If "remove" is TRUE, consume the message, the caller must free it then. * if "wait" is TRUE block until a message arrives (or the server exits). */ char_u * ! serverGetReply(HWND server, int expr, int remove, int wait) { int i; char_u *reply; --- 2167,2180 ---- /* * Get a reply from server "server". ! * When "expr_res" is non NULL, get the result of an expression, otherwise a * server2client() message. + * When non NULL, point to return code. 0 => OK, -1 => ERROR * If "remove" is TRUE, consume the message, the caller must free it then. * if "wait" is TRUE block until a message arrives (or the server exits). */ char_u * ! serverGetReply(HWND server, int *expr_res, int remove, int wait) { int i; char_u *reply; *************** *** 2177,2186 **** for (i = 0; i < REPLY_COUNT; ++i) { rep = REPLY_ITEM(i); ! if (rep->server == server && rep->expr_result == expr) { /* Save the values we've found for later */ reply = rep->reply; if (remove) { --- 2190,2202 ---- for (i = 0; i < REPLY_COUNT; ++i) { rep = REPLY_ITEM(i); ! if (rep->server == server ! && ((rep->expr_result != 0) == (expr_res != NULL))) { /* Save the values we've found for later */ reply = rep->reply; + if (expr_res != NULL) + *expr_res = rep->expr_result == 1 ? 0 : -1; if (remove) { *** ../vim60.161/src/proto/os_mswin.pro Tue Sep 25 21:49:35 2001 --- src/proto/os_mswin.pro Sun Feb 3 11:45:33 2002 *************** *** 47,53 **** int serverSendReply __ARGS((char_u *name, char_u *reply)); int serverSendToVim __ARGS((char_u *name, char_u *cmd, char_u **result, void *ptarget, int asExpr)); void serverForeground __ARGS((char_u *name)); ! char_u *serverGetReply __ARGS((HWND server, int expr, int remove, int wait)); void serverProcessPendingMessages __ARGS((void)); char *charset_id2name __ARGS((int id)); int get_logfont __ARGS((LOGFONT *lf, char_u *name, HDC printer_dc)); --- 47,53 ---- int serverSendReply __ARGS((char_u *name, char_u *reply)); int serverSendToVim __ARGS((char_u *name, char_u *cmd, char_u **result, void *ptarget, int asExpr)); void serverForeground __ARGS((char_u *name)); ! char_u *serverGetReply __ARGS((HWND server, int *expr_res, int remove, int wait)); void serverProcessPendingMessages __ARGS((void)); char *charset_id2name __ARGS((int id)); int get_logfont __ARGS((LOGFONT *lf, char_u *name, HDC printer_dc)); *** ../vim60.161/runtime/doc/eval.txt Tue Sep 25 21:40:34 2001 --- runtime/doc/eval.txt Sun Feb 3 11:51:14 2002 *************** *** 671,676 **** --- 679,685 ---- *v:servername* *servername-variable* v:servername The resulting registered |x11-clientserver| name if any. + Read-only. *v:shell_error* *shell_error-variable* v:shell_error Result of the last shell command. When non-zero, the last *************** *** 1189,1195 **** sourced script file name word under the cursor WORD under the cursor ! The {serverid} of the las Modifiers: :p expand to full path :h head (last path component removed) --- 1205,1212 ---- sourced script file name word under the cursor WORD under the cursor ! the {clientid} of the last received ! message |server2client()| Modifiers: :p expand to full path :h head (last path component removed) *************** *** 1864,1870 **** < When {lnum} is invalid or there is no non-blank line at or above it, zero is returned. ! *remote_expr()* remote_expr({server}, {string} [, {idvar}]) Send the {string} to {server}. The string is sent as an expression and the result is returned after evaluation. --- 1874,1880 ---- < When {lnum} is invalid or there is no non-blank line at or above it, zero is returned. ! *remote_expr()* *E449* remote_expr({server}, {string} [, {idvar}]) Send the {string} to {server}. The string is sent as an expression and the result is returned after evaluation. *************** *** 1873,1883 **** remote_read() is stored there. See also |clientserver| |RemoteReply|. {only available when compiled with the |+clientserver| feature} ! Note: Any errors will be reported in the server and may mess ! up the display. Examples: > :echo remote_expr("gvim", "2+2") ! :echo remote_expr("gvim-001", "b:current_syntax") < remote_foreground({server}) *remote_foreground()* --- 1883,1893 ---- remote_read() is stored there. See also |clientserver| |RemoteReply|. {only available when compiled with the |+clientserver| feature} ! Note: Any errors will cause a local error message to be issued ! and the result will be the empty string. Examples: > :echo remote_expr("gvim", "2+2") ! :echo remote_expr("gvim1", "b:current_syntax") < remote_foreground({server}) *remote_foreground()* *** ../vim60.161/runtime/tools/xcmdsrv_client.c Sun Sep 2 14:51:52 2001 --- runtime/tools/xcmdsrv_client.c Sun Feb 3 11:45:33 2002 *************** *** 32,50 **** #define __ARGS(x) x /* Client API */ ! char * sendToVim __ARGS((Display *dpy, char *name, char *cmd, int asKeys)); #ifdef MAIN /* A sample program */ main(int argc, char **argv) { ! char *res; if (argc == 4) { ! if ((res = sendToVim(XOpenDisplay(NULL), ! argv[2], argv[3], argv[1][0] != 'e')) != NULL) puts(res); exit(0); } else --- 32,55 ---- #define __ARGS(x) x /* Client API */ ! char * sendToVim __ARGS((Display *dpy, char *name, char *cmd, int asKeys, int *code)); #ifdef MAIN /* A sample program */ main(int argc, char **argv) { ! char *res; ! int code; if (argc == 4) { ! if ((res = sendToVim(XOpenDisplay(NULL), argv[2], argv[3], ! argv[1][0] != 'e', &code)) != NULL) ! { ! if (code) ! printf("Error code returned: %d\n", code); puts(res); + } exit(0); } else *************** *** 72,78 **** int delete, char **loose)); static int SendInit __ARGS((Display *dpy)); static char *SendEventProc __ARGS((Display *dpy, XEvent *eventPtr, ! int expect)); static int IsSerialName __ARGS((char *name)); /* Private variables */ --- 77,83 ---- int delete, char **loose)); static int SendInit __ARGS((Display *dpy)); static char *SendEventProc __ARGS((Display *dpy, XEvent *eventPtr, ! int expect, int *code)); static int IsSerialName __ARGS((char *name)); /* Private variables */ *************** *** 91,101 **** */ char * ! sendToVim(dpy, name, cmd, asKeys) Display *dpy; /* Where to send. */ char *name; /* Where to send. */ char *cmd; /* What to send. */ int asKeys; /* Interpret as keystrokes or expr ? */ { Window w; Atom *plist; --- 96,107 ---- */ char * ! sendToVim(dpy, name, cmd, asKeys, code) Display *dpy; /* Where to send. */ char *name; /* Where to send. */ char *cmd; /* What to send. */ int asKeys; /* Interpret as keystrokes or expr ? */ + int *code; /* Return code. 0 => OK */ { Window w; Atom *plist; *************** *** 225,231 **** { XNextEvent(dpy, &event); if (event.type == PropertyNotify && e->window == commWindow) ! if ((result = SendEventProc(dpy, &event, serial)) != NULL) return result; } } --- 231,237 ---- { XNextEvent(dpy, &event); if (event.type == PropertyNotify && e->window == commWindow) ! if ((result = SendEventProc(dpy, &event, serial, code)) != NULL) return result; } } *************** *** 335,341 **** entry = p; while ((*p != 0) && (!isspace(*p))) p++; ! if ((*p != 0) && (strcmp(name, p + 1) == 0)) { sscanf(entry, "%x", (uint*) &returnValue); break; --- 341,347 ---- entry = p; while ((*p != 0) && (!isspace(*p))) p++; ! if ((*p != 0) && (strcasecmp(name, p + 1) == 0)) { sscanf(entry, "%x", (uint*) &returnValue); break; *************** *** 392,405 **** } static char * ! SendEventProc(dpy, eventPtr, expected) Display *dpy; XEvent *eventPtr; /* Information about event. */ int expected; /* The one were waiting for */ { unsigned char *propInfo; unsigned char *p; int result, actualFormat; unsigned long numItems, bytesAfter; Atom actualType; --- 398,413 ---- } static char * ! SendEventProc(dpy, eventPtr, expected, code) Display *dpy; XEvent *eventPtr; /* Information about event. */ int expected; /* The one were waiting for */ + int *code; /* Return code. 0 => OK */ { unsigned char *propInfo; unsigned char *p; int result, actualFormat; + int retCode; unsigned long numItems, bytesAfter; Atom actualType; *************** *** 469,474 **** --- 477,483 ---- p += 2; gotSerial = 0; res = ""; + retCode = 0; while (((p-propInfo) < numItems) && (*p == '-')) { switch (p[1]) *************** *** 481,486 **** --- 490,499 ---- if (sscanf(p + 2, " %d", &serial) == 1) gotSerial = 1; break; + case 'c': + if (sscanf(p + 2, " %d", &retCode) != 1) + retCode = 0; + break; } while (*p != 0) p++; *************** *** 490,495 **** --- 503,510 ---- if (!gotSerial) continue; + if (code != NULL) + *code = retCode; return serial == expected ? strdup(res) : NULL; } else *************** *** 556,578 **** } /* ! * Check if name looks like it had a 3 digit serial number appended */ static int IsSerialName(str) ! char *str; { ! if (strlen(str) < 5) ! return FALSE; ! str = str + strlen(str) - 4; ! if (*str++ != '-') ! return FALSE; ! if (!isdigit(*str++)) ! return FALSE; ! if (!isdigit(*str++)) ! return FALSE; ! if (!isdigit(*str++)) ! return FALSE; ! return TRUE; } --- 571,584 ---- } /* ! * Check if "str" looks like it had a serial number appended. ! * Actually just checks if the name ends in a digit. */ static int IsSerialName(str) ! char *str; { ! int len = strlen(str); ! return (len > 1 && isdigit(str[len - 1])); } *** ../vim60.161/src/version.c Sun Feb 3 12:33:39 2002 --- src/version.c Sun Feb 3 12:29:58 2002 *************** *** 608,609 **** --- 608,611 ---- { /* Add new patch number below this line */ + /**/ + 162, /**/ -- hundred-and-one symptoms of being an internet addict: 167. You have more than 100 websites in your Bookmark. /// Bram Moolenaar -- Bram@moolenaar.net -- http://www.moolenaar.net \\\ ((( Creator of Vim -- http://vim.sf.net -- ftp://ftp.vim.org/pub/vim ))) \\\ Help me helping AIDS orphans in Uganda - http://iccf-holland.org ///