1/*
2   iso-8859-1.adapted conversion routines
3   Copyright (C) Bjoern Fernhomberg 2002,2003
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif /* HAVE_CONFIG_H */
23#include <stdlib.h>
24#include <string.h>
25#include <errno.h>
26
27#include <netatalk/endian.h>
28#include <atalk/unicode.h>
29#include <atalk/logger.h>
30
31#include "../../libatalk/unicode/byteorder.h"
32
33static size_t   iso8859_adapted_pull(void *,char **, size_t *, char **, size_t *);
34static size_t   iso8859_adapted_push(void *,char **, size_t *, char **, size_t *);
35
36struct charset_functions charset_iso8859_adapted =
37{
38	"ISO-8859-ADAPTED",
39	0,
40	iso8859_adapted_pull,
41	iso8859_adapted_push,
42	CHARSET_MULTIBYTE | CHARSET_PRECOMPOSED,
43	NULL,
44	NULL, NULL
45};
46
47
48/* ------------------------
49 * from unicode to iso8859_adapted code page
50*/
51
52static size_t iso8859_adapted_push( void *cd _U_, char **inbuf, size_t *inbytesleft,
53                         char **outbuf, size_t *outbytesleft)
54{
55    int len = 0;
56
57    while (*inbytesleft >= 2 && *outbytesleft >= 1) {
58	ucs2_t inptr = SVAL((*inbuf),0);
59        if ( inptr == 0x2122) {
60                SSVAL((*outbuf),0,0xAA);
61        }
62        else if ( inptr == 0x0192) {
63                SSVAL((*outbuf),0,0xC5);
64        }
65        else if ( inptr == 0x2014) {
66                SSVAL((*outbuf),0,0xD1);
67        }
68        else if ( inptr == 0x201C) {
69                SSVAL((*outbuf),0,0xD2);
70        }
71        else if ( inptr == 0x201D) {
72                SSVAL((*outbuf),0,0xD3);
73        }
74        else if ( inptr == 0x2018) {
75                SSVAL((*outbuf),0,0xD4);
76        }
77        else if ( inptr == 0x2019) {
78                SSVAL((*outbuf),0,0xD5);
79        }
80        else if ( inptr == 0x25CA) {
81                SSVAL((*outbuf),0,0xD7);
82        }
83	else if ( inptr > 0x0100) {
84		errno = EILSEQ;
85		return -1;
86        }
87	else {
88		SSVAL((*outbuf), 0, inptr);
89	}
90        (*inbuf)        +=2;
91        (*outbuf)       +=1;
92        (*inbytesleft) -=2;
93        (*outbytesleft)-=1;
94        len++;
95    }
96
97    if (*inbytesleft > 0) {
98        errno = E2BIG;
99        return -1;
100    }
101
102    return len;
103}
104
105/* ------------------------ */
106static size_t iso8859_adapted_pull ( void *cd _U_, char **inbuf, size_t *inbytesleft,
107                         char **outbuf, size_t *outbytesleft)
108{
109    unsigned char  *inptr;
110    size_t         len = 0;
111
112    while (*inbytesleft >= 1 && *outbytesleft >= 2) {
113        inptr = (unsigned char *) *inbuf;
114
115	if ( *inptr == 0xAA) {
116		SSVAL((*outbuf),0,0x2122);
117	}
118	else if ( *inptr == 0xC5) {
119		SSVAL((*outbuf),0,0x0192);
120	}
121	else if ( *inptr == 0xD1) {
122		SSVAL((*outbuf),0,0x2014);
123	}
124	else if ( *inptr == 0xD2) {
125		SSVAL((*outbuf),0,0x201C);
126	}
127	else if ( *inptr == 0xD3) {
128		SSVAL((*outbuf),0,0x201D);
129	}
130	else if ( *inptr == 0xD4) {
131		SSVAL((*outbuf),0,0x2018);
132	}
133	else if ( *inptr == 0xD5) {
134		SSVAL((*outbuf),0,0x2019);
135	}
136	else if ( *inptr == 0xD7) {
137		SSVAL((*outbuf),0,0x25CA);
138	}
139	else {
140		SSVAL((*outbuf),0,(*inptr));
141	}
142        (*outbuf)      +=2;
143	(*outbytesleft)-=2;
144        (*inbuf)        +=1;
145	(*inbytesleft) -=1;
146	len++;
147    }
148
149    if (*inbytesleft > 0) {
150        errno = E2BIG;
151        return (size_t) -1;
152    }
153    return len;
154}
155
156