/* Copyright 1997 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdlib.h>

#include "encpriv.h"

#include "eightbit.h"

typedef struct EightBit_Encoding
{
    EncodingPriv e;
    encoding_table table; /* 128-entry table for codes 0x80-0xFF */
} EightBit_Encoding;

/*
 * Routines for KOI-8R (Cyrillic)
 * Number: 2084
 * Names: KOI8-R
 *        csKOI8R
 */

static int eightbit_reset(Encoding *e, int for_encoding)
{
    EightBit_Encoding *ee = (EightBit_Encoding *) e;

    if (!ee->table)
        ee->table = encoding_load_map_file(e->list_entry->preload);

    return ee->table != NULL;
}

static unsigned int eightbit_read(EncodingPriv *e,
			   encoding_read_callback_fn ucs_out,
                           const char *s,
                           unsigned int n,
                           void *handle)
{
    EightBit_Encoding *ee = (EightBit_Encoding *) e;
    unsigned int count;
    UCS2 *table = encoding_table_ptr(ee->table);

    for (count = n; count; count--)
    {
        char c = *s++;
        UCS4 u = c < 0x80 ? c : table[c - 0x80];

        if (u == NULL_UCS2)
            u = 0xFFFD;

        if (ucs_out)
            if (ucs_out(handle, u))
                break;
    }

    return n - count;
}

static int eightbit_write(EncodingPriv *e, UCS4 u, char **s, int *bufsize)
{
    EightBit_Encoding *ee = (EightBit_Encoding *) e;
    int i, c;

    if ( --(*bufsize) < 0 || !s)
	return 0;

    if (u < 0x80)
	c = u;
    else if ((i = encoding_lookup_in_table(u, ee->table)) != -1)
	c = i + 0x80;
    else
	c = '?';

    (*s)[0] = c;
    (*s)++;
    return 1;
}

static void eightbit_delete(EncodingPriv *e)
{
    EightBit_Encoding *ee = (EightBit_Encoding *) e;
    if (ee->table)
	encoding_discard_map_file(ee->table);
}

EncodingPriv enc_eightbit =
{
    eightbit_read,
    eightbit_reset,
    sizeof(EightBit_Encoding) - sizeof(EncodingPriv),
    eightbit_delete,
    0,
    eightbit_write
};