Added second part of helper functions for CharSetandLanguageNegotaiation-3 Model.
[yaz-moved-to-github.git] / zoom / zoom-c.c
index 96321be..267bb2c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: zoom-c.c,v 1.22 2002-01-24 19:33:09 adam Exp $
+ * $Id: zoom-c.c,v 1.30 2002-05-19 15:39:54 oleg Exp $
  *
  * ZOOM layer for C, connections, result sets, queries.
  */
@@ -9,6 +9,7 @@
 #include <yaz/log.h>
 #include <yaz/pquery.h>
 #include <yaz/diagbib1.h>
+#include <yaz/charneg.h>
 
 #include "zoom-p.h"
 
 #include <sys/poll.h>
 #endif
 
+static int ZOOM_connection_send_init (ZOOM_connection c);
+
 static ZOOM_Event ZOOM_Event_create (int kind)
 {
-    ZOOM_Event event = xmalloc (sizeof(*event));
+    ZOOM_Event event = (ZOOM_Event) xmalloc (sizeof(*event));
     event->kind = kind;
     event->next = 0;
     event->prev = 0;
@@ -89,7 +92,7 @@ ZOOM_task ZOOM_connection_add_task (ZOOM_connection c, int which)
     ZOOM_task *taskp = &c->tasks;
     while (*taskp)
        taskp = &(*taskp)->next;
-    *taskp = xmalloc (sizeof(**taskp));
+    *taskp = (ZOOM_task) xmalloc (sizeof(**taskp));
     (*taskp)->running = 0;
     (*taskp)->which = which;
     (*taskp)->next = 0;
@@ -134,9 +137,10 @@ static ZOOM_record record_cache_lookup (ZOOM_resultset r,
                                         int pos,
                                         const char *elementSetName);
 
-ZOOM_connection ZOOM_connection_create (ZOOM_options options)
+ZOOM_API(ZOOM_connection)
+ZOOM_connection_create (ZOOM_options options)
 {
-    ZOOM_connection c = xmalloc (sizeof(*c));
+    ZOOM_connection c = (ZOOM_connection) xmalloc (sizeof(*c));
 
     c->cs = 0;
     c->mask = 0;
@@ -153,6 +157,8 @@ ZOOM_connection ZOOM_connection_create (ZOOM_options options)
 
     c->host_port = 0;
     c->proxy = 0;
+    
+    c->charset = c->lang = 0;
 
     c->cookie_out = 0;
     c->cookie_in = 0;
@@ -197,7 +203,8 @@ static char **set_DatabaseNames (ZOOM_connection con, ZOOM_options options,
     }
     else
        cp = "Default";
-    databaseNames = odr_malloc (con->odr_out, no * sizeof(*databaseNames));
+    databaseNames = (char**)
+        odr_malloc (con->odr_out, no * sizeof(*databaseNames));
     no = 0;
     while (*cp)
     {
@@ -211,7 +218,7 @@ static char **set_DatabaseNames (ZOOM_connection con, ZOOM_options options,
        }
        /* cp ptr to first char of db name, c is char
           following db name */
-       databaseNames[no] = odr_malloc (con->odr_out, 1+c-cp);
+       databaseNames[no] = (char*) odr_malloc (con->odr_out, 1+c-cp);
        memcpy (databaseNames[no], cp, c-cp);
        databaseNames[no++][c-cp] = '\0';
        cp = c;
@@ -223,7 +230,8 @@ static char **set_DatabaseNames (ZOOM_connection con, ZOOM_options options,
     return databaseNames;
 }
 
-ZOOM_connection ZOOM_connection_new (const char *host, int portnum)
+ZOOM_API(ZOOM_connection)
+ZOOM_connection_new (const char *host, int portnum)
 {
     ZOOM_connection c = ZOOM_connection_create (0);
 
@@ -231,8 +239,9 @@ ZOOM_connection ZOOM_connection_new (const char *host, int portnum)
     return c;
 }
 
-void ZOOM_connection_connect(ZOOM_connection c,
-                             const char *host, int portnum)
+ZOOM_API(void)
+ZOOM_connection_connect(ZOOM_connection c,
+                               const char *host, int portnum)
 {
     const char *val;
     ZOOM_task task;
@@ -243,6 +252,18 @@ void ZOOM_connection_connect(ZOOM_connection c,
     else
        c->proxy = 0;
 
+    val = ZOOM_options_get (c->options, "charset");
+    if (val && *val)
+       c->charset = xstrdup (val);
+    else
+       c->charset = 0;
+
+    val = ZOOM_options_get (c->options, "lang");
+    if (val && *val)
+       c->lang = xstrdup (val);
+    else
+       c->lang = 0;
+
     if (portnum)
     {
        char hostn[128];
@@ -267,9 +288,10 @@ void ZOOM_connection_connect(ZOOM_connection c,
     }
 }
 
-ZOOM_query ZOOM_query_create(void)
+ZOOM_API(ZOOM_query)
+ZOOM_query_create(void)
 {
-    ZOOM_query s = xmalloc (sizeof(*s));
+    ZOOM_query s = (ZOOM_query) xmalloc (sizeof(*s));
 
     s->refcount = 1;
     s->query = 0;
@@ -279,7 +301,8 @@ ZOOM_query ZOOM_query_create(void)
     return s;
 }
 
-void ZOOM_query_destroy(ZOOM_query s)
+ZOOM_API(void)
+ZOOM_query_destroy(ZOOM_query s)
 {
     if (!s)
        return;
@@ -293,9 +316,10 @@ void ZOOM_query_destroy(ZOOM_query s)
     }
 }
 
-int ZOOM_query_prefix(ZOOM_query s, const char *str)
+ZOOM_API(int)
+ZOOM_query_prefix(ZOOM_query s, const char *str)
 {
-    s->query = odr_malloc (s->odr, sizeof(*s->query));
+    s->query = (Z_Query *) odr_malloc (s->odr, sizeof(*s->query));
     s->query->which = Z_Query_type_1;
     s->query->u.type_1 =  p_query_rpn(s->odr, PROTO_Z3950, str);
     if (!s->query->u.type_1)
@@ -303,7 +327,8 @@ int ZOOM_query_prefix(ZOOM_query s, const char *str)
     return 0;
 }
 
-int ZOOM_query_sortby(ZOOM_query s, const char *criteria)
+ZOOM_API(int)
+ZOOM_query_sortby(ZOOM_query s, const char *criteria)
 {
     s->sort_spec = yaz_sort_spec (s->odr, criteria);
     if (!s->sort_spec)
@@ -313,7 +338,8 @@ int ZOOM_query_sortby(ZOOM_query s, const char *criteria)
 
 static int do_write(ZOOM_connection c);
 
-void ZOOM_connection_destroy(ZOOM_connection c)
+ZOOM_API(void)
+ZOOM_connection_destroy(ZOOM_connection c)
 {
     ZOOM_resultset r;
     if (!c)
@@ -330,6 +356,11 @@ void ZOOM_connection_destroy(ZOOM_connection c)
     ZOOM_options_destroy (c->options);
     ZOOM_connection_remove_tasks (c);
     xfree (c->host_port);
+    xfree (c->proxy);
+    xfree (c->charset);
+    xfree (c->lang);
+    xfree (c->cookie_out);
+    xfree (c->cookie_in);
     xfree (c);
 }
 
@@ -340,7 +371,7 @@ void ZOOM_resultset_addref (ZOOM_resultset r)
 }
 ZOOM_resultset ZOOM_resultset_create ()
 {
-    ZOOM_resultset r = xmalloc (sizeof(*r));
+    ZOOM_resultset r = (ZOOM_resultset) xmalloc (sizeof(*r));
 
     r->refcount = 1;
     r->size = 0;
@@ -358,7 +389,8 @@ ZOOM_resultset ZOOM_resultset_create ()
     return r;
 }
 
-ZOOM_resultset ZOOM_connection_search_pqf(ZOOM_connection c, const char *q)
+ZOOM_API(ZOOM_resultset)
+ZOOM_connection_search_pqf(ZOOM_connection c, const char *q)
 {
     ZOOM_resultset r;
     ZOOM_query s = ZOOM_query_create();
@@ -370,7 +402,8 @@ ZOOM_resultset ZOOM_connection_search_pqf(ZOOM_connection c, const char *q)
     return r;
 }
 
-ZOOM_resultset ZOOM_connection_search(ZOOM_connection c, ZOOM_query q)
+ZOOM_API(ZOOM_resultset)
+ZOOM_connection_search(ZOOM_connection c, ZOOM_query q)
 {
     ZOOM_resultset r = ZOOM_resultset_create ();
     ZOOM_task task;
@@ -408,7 +441,8 @@ ZOOM_resultset ZOOM_connection_search(ZOOM_connection c, ZOOM_query q)
     return r;
 }
 
-void ZOOM_resultset_destroy(ZOOM_resultset r)
+ZOOM_API(void)
+ZOOM_resultset_destroy(ZOOM_resultset r)
 {
     if (!r)
         return;
@@ -444,7 +478,8 @@ void ZOOM_resultset_destroy(ZOOM_resultset r)
     }
 }
 
-size_t ZOOM_resultset_size (ZOOM_resultset r)
+ZOOM_API(size_t)
+ZOOM_resultset_size (ZOOM_resultset r)
 {
     return r->size;
 }
@@ -481,8 +516,9 @@ static void ZOOM_resultset_retrieve (ZOOM_resultset r,
            ;
 }
 
-void ZOOM_resultset_records (ZOOM_resultset r, ZOOM_record *recs,
-                             size_t start, size_t count)
+ZOOM_API(void)
+ZOOM_resultset_records (ZOOM_resultset r, ZOOM_record *recs,
+                               size_t start, size_t count)
 {
     int force_present = 0;
 
@@ -518,7 +554,15 @@ static int do_connect (ZOOM_connection c)
     {
        int ret = cs_connect (c->cs, add);
        yaz_log (LOG_DEBUG, "cs_connect returned %d", ret);
-       if (ret >= 0)
+        if (ret == 0)
+        {
+            ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_CONNECT);
+            ZOOM_connection_put_event(c, event);
+            ZOOM_connection_send_init(c);
+            c->state = STATE_ESTABLISHED;
+            return 1;
+        }
+        else if (ret > 0)
        {
            c->state = STATE_CONNECTING; 
             c->mask = ZOOM_SELECT_EXCEPT;
@@ -599,7 +643,8 @@ static int ZOOM_connection_send_init (ZOOM_connection c)
     const char *impname;
     Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_initRequest);
     Z_InitRequest *ireq = apdu->u.initRequest;
-    Z_IdAuthentication *auth = odr_malloc(c->odr_out, sizeof(*auth));
+    Z_IdAuthentication *auth = (Z_IdAuthentication *)
+        odr_malloc(c->odr_out, sizeof(*auth));
     const char *auth_groupId = ZOOM_options_get (c->options, "group");
     const char *auth_userId = ZOOM_options_get (c->options, "user");
     const char *auth_password = ZOOM_options_get (c->options, "pass");
@@ -617,7 +662,7 @@ static int ZOOM_connection_send_init (ZOOM_connection c)
     
     impname = ZOOM_options_get (c->options, "implementationName");
     ireq->implementationName =
-       odr_malloc (c->odr_out, 15 + (impname ? strlen(impname) : 0));
+       (char *) odr_malloc (c->odr_out, 15 + (impname ? strlen(impname) : 0));
     strcpy (ireq->implementationName, "");
     if (impname)
     {
@@ -633,26 +678,29 @@ static int ZOOM_connection_send_init (ZOOM_connection c)
     
     if (auth_groupId || auth_password)
     {
-       Z_IdPass *pass = odr_malloc(c->odr_out, sizeof(*pass));
+       Z_IdPass *pass = (Z_IdPass *) odr_malloc(c->odr_out, sizeof(*pass));
        int i = 0;
        pass->groupId = 0;
        if (auth_groupId && *auth_groupId)
        {
-           pass->groupId = odr_malloc(c->odr_out, strlen(auth_groupId)+1);
+           pass->groupId = (char *)
+                odr_malloc(c->odr_out, strlen(auth_groupId)+1);
            strcpy(pass->groupId, auth_groupId);
            i++;
        }
        pass->userId = 0;
        if (auth_userId && *auth_userId)
        {
-           pass->userId = odr_malloc(c->odr_out, strlen(auth_userId)+1);
+           pass->userId = (char *)
+                odr_malloc(c->odr_out, strlen(auth_userId)+1);
            strcpy(pass->userId, auth_userId);
            i++;
        }
        pass->password = 0;
        if (auth_password && *auth_password)
        {
-           pass->password = odr_malloc(c->odr_out, strlen(auth_password)+1);
+           pass->password = (char *)
+                odr_malloc(c->odr_out, strlen(auth_password)+1);
            strcpy(pass->password, auth_password);
            i++;
        }
@@ -666,13 +714,32 @@ static int ZOOM_connection_send_init (ZOOM_connection c)
     else if (auth_userId)
     {
        auth->which = Z_IdAuthentication_open;
-       auth->u.open = odr_malloc(c->odr_out, strlen(auth_userId)+1);
+       auth->u.open = (char *)
+            odr_malloc(c->odr_out, strlen(auth_userId)+1);
        strcpy(auth->u.open, auth_userId);
        ireq->idAuthentication = auth;
     }
     if (c->proxy)
        yaz_oi_set_string_oidval(&ireq->otherInfo, c->odr_out,
                                 VAL_PROXY, 1, c->host_port);
+    if (c->charset||c->lang)
+    {
+       Z_OtherInformation **oi;
+       Z_OtherInformationUnit *oi_unit;
+       
+       yaz_oi_APDU(apdu, &oi);
+       
+       if (oi_unit = yaz_oi_update(oi, c->odr_out, NULL, 0, 0))
+       {
+               ODR_MASK_SET(ireq->options, Z_Options_negotiationModel);
+               
+               oi_unit->which = Z_OtherInfo_externallyDefinedInfo;
+               oi_unit->information.externallyDefinedInfo =
+                       yaz_set_proposal_charneg(c->odr_out,
+                               (const char **)&c->charset, (c->charset) ? 1:0,
+                               (const char **)&c->lang, (c->lang) ? 1:0, 1);
+       }
+    }
     assert (apdu);
     send_APDU (c, apdu);
     
@@ -751,7 +818,8 @@ static int ZOOM_connection_send_search (ZOOM_connection c)
     }
     if (smallSetElementSetName && *smallSetElementSetName)
     {
-       Z_ElementSetNames *esn = odr_malloc (c->odr_out, sizeof(*esn));
+       Z_ElementSetNames *esn = (Z_ElementSetNames *)
+            odr_malloc (c->odr_out, sizeof(*esn));
        
        esn->which = Z_ElementSetNames_generic;
        esn->u.generic = odr_strdup (c->odr_out, smallSetElementSetName);
@@ -759,7 +827,8 @@ static int ZOOM_connection_send_search (ZOOM_connection c)
     }
     if (mediumSetElementSetName && *mediumSetElementSetName)
     {
-       Z_ElementSetNames *esn = odr_malloc (c->odr_out, sizeof(*esn));
+       Z_ElementSetNames *esn = (Z_ElementSetNames *)
+            odr_malloc (c->odr_out, sizeof(*esn));
        
        esn->which = Z_ElementSetNames_generic;
        esn->u.generic = odr_strdup (c->odr_out, mediumSetElementSetName);
@@ -828,7 +897,8 @@ static void response_diag (ZOOM_connection c, Z_DiagRec *p)
     c->error = *r->condition;
 }
 
-ZOOM_record ZOOM_record_clone (ZOOM_record srec)
+ZOOM_API(ZOOM_record)
+ZOOM_record_clone (ZOOM_record srec)
 {
     char *buf;
     int size;
@@ -840,7 +910,7 @@ ZOOM_record ZOOM_record_clone (ZOOM_record srec)
        return 0;
     buf = odr_getbuf (odr_enc, &size, 0);
     
-    nrec = xmalloc (sizeof(*nrec));
+    nrec = (ZOOM_record) xmalloc (sizeof(*nrec));
     nrec->odr = odr_createmem(ODR_DECODE);
     nrec->wrbuf_marc = 0;
     odr_setbuf (nrec->odr, buf, size, 0);
@@ -850,18 +920,21 @@ ZOOM_record ZOOM_record_clone (ZOOM_record srec)
     return nrec;
 }
 
-ZOOM_record ZOOM_resultset_record_immediate (ZOOM_resultset s,size_t pos)
+ZOOM_API(ZOOM_record)
+ZOOM_resultset_record_immediate (ZOOM_resultset s,size_t pos)
 {
     return record_cache_lookup (s, pos, 0);
 }
 
-ZOOM_record ZOOM_resultset_record (ZOOM_resultset r, size_t pos)
+ZOOM_API(ZOOM_record)
+ZOOM_resultset_record (ZOOM_resultset r, size_t pos)
 {
     ZOOM_resultset_retrieve (r, 1, pos, 1);
     return ZOOM_resultset_record_immediate (r, pos);
 }
 
-void ZOOM_record_destroy (ZOOM_record rec)
+ZOOM_API(void)
+ZOOM_record_destroy (ZOOM_record rec)
 {
     if (!rec)
        return;
@@ -871,9 +944,14 @@ void ZOOM_record_destroy (ZOOM_record rec)
     xfree (rec);
 }
 
-void *ZOOM_record_get (ZOOM_record rec, const char *type, size_t *len)
+ZOOM_API(const char *)
+ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
 {
     Z_NamePlusRecord *npr;
+    
+    if (len)
+       *len = 0; /* default return */
+       
     if (!rec)
        return 0;
     npr = rec->npr;
@@ -881,6 +959,7 @@ void *ZOOM_record_get (ZOOM_record rec, const char *type, size_t *len)
        return 0;
     if (!strcmp (type, "database"))
     {
+       if (len) *len = strlen(npr->databaseName)+1;
        return npr->databaseName;
     }
     else if (!strcmp (type, "syntax"))
@@ -890,54 +969,103 @@ void *ZOOM_record_get (ZOOM_record rec, const char *type, size_t *len)
            Z_External *r = (Z_External *) npr->u.databaseRecord;
            oident *ent = oid_getentbyoid(r->direct_reference);
            if (ent)
+           {
+               if (len) *len = strlen(ent->desc)+1;
                return ent->desc;
+           }
        }
        return "none";
     }
-    else if (!strcmp (type, "render"))
+    else if (!strcmp (type, "render") && 
+             npr->which == Z_NamePlusRecord_databaseRecord)
     {
-       if (npr->which == Z_NamePlusRecord_databaseRecord)
-       {
-           Z_External *r = (Z_External *) npr->u.databaseRecord;
-           oident *ent = oid_getentbyoid(r->direct_reference);
-           
-           if (r->which == Z_External_sutrs)
-           {
-               *len = r->u.sutrs->len;
-               return r->u.sutrs->buf;
-           }
-           else if (r->which == Z_External_octet)
-           {
-               switch (ent->value)
-               {
-               case VAL_SOIF:
-               case VAL_HTML:
-               case VAL_SUTRS:
-                   break;
-               case VAL_TEXT_XML:
-               case VAL_APPLICATION_XML:
-                   break;
-               default:
-                   if (!rec->wrbuf_marc)
-                       rec->wrbuf_marc = wrbuf_alloc();
-                    wrbuf_rewind (rec->wrbuf_marc);
-                   if (marc_display_wrbuf (r->u.octet_aligned->buf,
-                                       rec->wrbuf_marc, 0,
-                                           r->u.octet_aligned->len) > 0)
-                   {
-                       *len = wrbuf_len(rec->wrbuf_marc);
-                       return wrbuf_buf(rec->wrbuf_marc);
-                   }
-               }
-               *len = r->u.octet_aligned->len;
-               return r->u.octet_aligned->buf;
-           }
-           else if (r->which == Z_External_grs1)
-           {
-               *len = 5;
-               return "GRS-1";
-           }
-       }
+        Z_External *r = (Z_External *) npr->u.databaseRecord;
+        oident *ent = oid_getentbyoid(r->direct_reference);
+        
+        if (r->which == Z_External_sutrs)
+        {
+            if (len) *len = r->u.sutrs->len;
+            return (const char *) r->u.sutrs->buf;
+        }
+        else if (r->which == Z_External_octet)
+        {
+            switch (ent->value)
+            {
+            case VAL_SOIF:
+            case VAL_HTML:
+            case VAL_SUTRS:
+                break;
+            case VAL_TEXT_XML:
+            case VAL_APPLICATION_XML:
+                break;
+            default:
+                if (!rec->wrbuf_marc)
+                    rec->wrbuf_marc = wrbuf_alloc();
+                wrbuf_rewind (rec->wrbuf_marc);
+                if (yaz_marc_decode ((const char *)
+                                     r->u.octet_aligned->buf,
+                                     rec->wrbuf_marc, 0,
+                                     r->u.octet_aligned->len,
+                                     0) > 0)
+                {
+                    if (len) *len = wrbuf_len(rec->wrbuf_marc);
+                    return wrbuf_buf(rec->wrbuf_marc);
+                }
+            }
+            if (len) *len = r->u.octet_aligned->len;
+            return (const char *) r->u.octet_aligned->buf;
+        }
+        else if (r->which == Z_External_grs1)
+        {
+            if (len) *len = 5;
+            return "GRS-1";
+        }
+       return 0;
+    }
+    else if (!strcmp (type, "xml") && 
+             npr->which == Z_NamePlusRecord_databaseRecord)
+    {
+        Z_External *r = (Z_External *) npr->u.databaseRecord;
+        oident *ent = oid_getentbyoid(r->direct_reference);
+        
+        if (r->which == Z_External_sutrs)
+        {
+            if (len) *len = r->u.sutrs->len;
+            return (const char *) r->u.sutrs->buf;
+        }
+        else if (r->which == Z_External_octet)
+        {
+            switch (ent->value)
+            {
+            case VAL_SOIF:
+            case VAL_HTML:
+            case VAL_SUTRS:
+                break;
+            case VAL_TEXT_XML:
+            case VAL_APPLICATION_XML:
+                break;
+            default:
+                if (!rec->wrbuf_marc)
+                    rec->wrbuf_marc = wrbuf_alloc();
+                wrbuf_rewind (rec->wrbuf_marc);
+                if (yaz_marc_decode ((const char *)
+                                     r->u.octet_aligned->buf,
+                                     rec->wrbuf_marc, 0,
+                                     r->u.octet_aligned->len,
+                                     1) > 0)
+                {
+                    if (len) *len = wrbuf_len(rec->wrbuf_marc);
+                    return wrbuf_buf(rec->wrbuf_marc);
+                }
+            }
+            if (len) *len = r->u.octet_aligned->len;
+            return (const char *) r->u.octet_aligned->buf;
+        }
+        else if (r->which == Z_External_grs1)
+        {
+            if (len) *len = 5;
+            return "GRS-1";
+        }
        return 0;
     }
     else if (!strcmp (type, "raw"))
@@ -948,18 +1076,18 @@ void *ZOOM_record_get (ZOOM_record rec, const char *type, size_t *len)
            
            if (r->which == Z_External_sutrs)
            {
-               *len = r->u.sutrs->len;
-               return r->u.sutrs->buf;
+               if (len) *len = r->u.sutrs->len;
+               return (const char *) r->u.sutrs->buf;
            }
            else if (r->which == Z_External_octet)
            {
-               *len = r->u.octet_aligned->len;
-               return r->u.octet_aligned->buf;
+               if (len) *len = r->u.octet_aligned->len;
+               return (const char *) r->u.octet_aligned->buf;
            }
            else /* grs-1, explain, ... */
            {
-               *len = -1;
-                return (Z_External *) npr->u.databaseRecord;
+               if (len) *len = -1;
+                return (const char *) npr->u.databaseRecord;
            }
        }
        return 0;
@@ -989,7 +1117,7 @@ static void record_cache_add (ZOOM_resultset r,
            }
        }
     }
-    rc = odr_malloc (r->odr, sizeof(*rc));
+    rc = (ZOOM_record_cache) odr_malloc (r->odr, sizeof(*rc));
     rc->rec.npr = npr; 
     rc->rec.odr = 0;
     rc->rec.wrbuf_marc = 0;
@@ -1234,7 +1362,8 @@ static int send_present (ZOOM_connection c)
 
     if (schema && *schema)
     {
-       Z_RecordComposition *compo = odr_malloc (c->odr_out, sizeof(*compo));
+       Z_RecordComposition *compo = (Z_RecordComposition *)
+            odr_malloc (c->odr_out, sizeof(*compo));
 
         req->recordComposition = compo;
         compo->which = Z_RecordComp_complex;
@@ -1275,8 +1404,10 @@ static int send_present (ZOOM_connection c)
     }
     else if (element && *element)
     {
-       Z_ElementSetNames *esn = odr_malloc (c->odr_out, sizeof(*esn));
-       Z_RecordComposition *compo = odr_malloc (c->odr_out, sizeof(*compo));
+       Z_ElementSetNames *esn = (Z_ElementSetNames *)
+            odr_malloc (c->odr_out, sizeof(*esn));
+       Z_RecordComposition *compo = (Z_RecordComposition *)
+            odr_malloc (c->odr_out, sizeof(*compo));
        
        esn->which = Z_ElementSetNames_generic;
        esn->u.generic = odr_strdup (c->odr_out, element);
@@ -1289,9 +1420,10 @@ static int send_present (ZOOM_connection c)
     return 1;
 }
 
-ZOOM_scanset ZOOM_connection_scan (ZOOM_connection c, const char *start)
+ZOOM_API(ZOOM_scanset)
+ZOOM_connection_scan (ZOOM_connection c, const char *start)
 {
-    ZOOM_scanset scan = xmalloc (sizeof(*scan));
+    ZOOM_scanset scan = (ZOOM_scanset) xmalloc (sizeof(*scan));
 
     scan->connection = c;
     scan->odr = odr_createmem (ODR_DECODE);
@@ -1316,7 +1448,8 @@ ZOOM_scanset ZOOM_connection_scan (ZOOM_connection c, const char *start)
     return scan;
 }
 
-void ZOOM_scanset_destroy (ZOOM_scanset scan)
+ZOOM_API(void)
+ZOOM_scanset_destroy (ZOOM_scanset scan)
 {
     if (!scan)
         return;
@@ -1330,7 +1463,7 @@ void ZOOM_scanset_destroy (ZOOM_scanset scan)
     }
 }
 
-int send_scan (ZOOM_connection c)
+static int send_scan (ZOOM_connection c)
 {
     ZOOM_scanset scan;
     Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_scanRequest);
@@ -1362,15 +1495,17 @@ int send_scan (ZOOM_connection c)
     return 1;
 }
 
-size_t ZOOM_scanset_size (ZOOM_scanset scan)
+ZOOM_API(size_t)
+ZOOM_scanset_size (ZOOM_scanset scan)
 {
     if (!scan || !scan->scan_response || !scan->scan_response->entries)
         return 0;
     return scan->scan_response->entries->num_entries;
 }
 
-const char *ZOOM_scanset_term (ZOOM_scanset scan, size_t pos,
-                               int *occ, size_t *len)
+ZOOM_API(const char *)
+ZOOM_scanset_term (ZOOM_scanset scan, size_t pos,
+                               int *occ, int *len)
 {
     const char *term = 0;
     size_t noent = ZOOM_scanset_size (scan);
@@ -1386,7 +1521,7 @@ const char *ZOOM_scanset_term (ZOOM_scanset scan, size_t pos,
         
         if (t->term->which == Z_Term_general)
         {
-            term = t->term->u.general->buf;
+            term = (const char *) t->term->u.general->buf;
             *len = t->term->u.general->len;
         }
         *occ = t->globalOccurrences ? *t->globalOccurrences : 0;
@@ -1394,12 +1529,14 @@ const char *ZOOM_scanset_term (ZOOM_scanset scan, size_t pos,
     return term;
 }
 
-const char *ZOOM_scanset_option_get (ZOOM_scanset scan, const char *key)
+ZOOM_API(const char *)
+ZOOM_scanset_option_get (ZOOM_scanset scan, const char *key)
 {
     return ZOOM_options_get (scan->options, key);
 }
 
-void ZOOM_scanset_option_set (ZOOM_scanset scan, const char *key,
+ZOOM_API(void)
+ZOOM_scanset_option_set (ZOOM_scanset scan, const char *key,
                               const char *val)
 {
     ZOOM_options_set (scan->options, key, val);
@@ -1486,6 +1623,24 @@ static void handle_apdu (ZOOM_connection c, Z_APDU *apdu)
             }
            ZOOM_connection_exec_task (c);
        }
+       if (ODR_MASK_GET(initrs->options, Z_Options_negotiationModel))
+       {
+               NMEM tmpmem = nmem_create();
+               Z_CharSetandLanguageNegotiation *p =
+                       yaz_get_charneg_record(initrs->otherInfo);
+               
+               if (p)
+               {
+                       char *charset, *lang;
+                       int selected;
+                       
+                       yaz_get_response_charneg(tmpmem, p, &charset, &lang, &selected);
+                       yaz_log(LOG_DEBUG, "Target accepted: charset - %s, language - %s, select - %d",
+                               charset, lang, selected);
+                       
+                       nmem_destroy(tmpmem);
+               }
+       }       
        break;
     case Z_APDU_searchResponse:
        handle_search_response (c, apdu->u.searchResponse);
@@ -1585,49 +1740,57 @@ static int do_write(ZOOM_connection c)
 }
 
 
-const char *ZOOM_connection_option_get (ZOOM_connection c, const char *key)
+ZOOM_API(const char *)
+ZOOM_connection_option_get (ZOOM_connection c, const char *key)
 {
     return ZOOM_options_get (c->options, key);
 }
 
-void ZOOM_connection_option_set (ZOOM_connection c, const char *key,
+ZOOM_API(void)
+ZOOM_connection_option_set (ZOOM_connection c, const char *key,
                                   const char *val)
 {
     ZOOM_options_set (c->options, key, val);
 }
 
-const char *ZOOM_resultset_option_get (ZOOM_resultset r, const char *key)
+ZOOM_API(const char *)
+ZOOM_resultset_option_get (ZOOM_resultset r, const char *key)
 {
     return ZOOM_options_get (r->options, key);
 }
 
-void ZOOM_resultset_option_set (ZOOM_resultset r, const char *key,
+ZOOM_API(void)
+ZOOM_resultset_option_set (ZOOM_resultset r, const char *key,
                                   const char *val)
 {
     ZOOM_options_set (r->options, key, val);
 }
 
 
-int ZOOM_connection_errcode (ZOOM_connection c)
+ZOOM_API(int)
+ZOOM_connection_errcode (ZOOM_connection c)
 {
     return ZOOM_connection_error (c, 0, 0);
 }
 
-const char *ZOOM_connection_errmsg (ZOOM_connection c)
+ZOOM_API(const char *)
+ZOOM_connection_errmsg (ZOOM_connection c)
 {
     const char *msg;
     ZOOM_connection_error (c, &msg, 0);
     return msg;
 }
 
-const char *ZOOM_connection_addinfo (ZOOM_connection c)
+ZOOM_API(const char *)
+ZOOM_connection_addinfo (ZOOM_connection c)
 {
     const char *addinfo;
     ZOOM_connection_error (c, 0, &addinfo);
     return addinfo;
 }
 
-int ZOOM_connection_error (ZOOM_connection c, const char **cp,
+ZOOM_API(int)
+ZOOM_connection_error (ZOOM_connection c, const char **cp,
                            const char **addinfo)
 {
     int error = c->error;
@@ -1667,7 +1830,7 @@ int ZOOM_connection_error (ZOOM_connection c, const char **cp,
     return c->error;
 }
 
-int ZOOM_connection_do_io(ZOOM_connection c, int mask)
+static int ZOOM_connection_do_io(ZOOM_connection c, int mask)
 {
     ZOOM_Event event = 0;
     int r = cs_look(c->cs);
@@ -1720,14 +1883,16 @@ int ZOOM_connection_do_io(ZOOM_connection c, int mask)
     return 1;
 }
 
-int ZOOM_connection_last_event(ZOOM_connection cs)
+ZOOM_API(int)
+ZOOM_connection_last_event(ZOOM_connection cs)
 {
     if (!cs)
         return ZOOM_EVENT_NONE;
     return cs->last_event;
 }
 
-int ZOOM_event (int no, ZOOM_connection *cs)
+ZOOM_API(int)
+ZOOM_event (int no, ZOOM_connection *cs)
 {
 #if HAVE_SYS_POLL_H
     struct pollfd pollfds[1024];