// Hey ! emacs, it is an -*- objective-c -*- file

/*

    Webster Access, a program to use NeXT online Webster dictionary.
    Copyright (C) 1994 Benoit Grange, ben@fizz.fdn.org

    This program 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 of the License, or
    (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#import "WebsterVolume.h"
#import "WebsterWord.h"
#import "codebook.h"

@implementation WebsterWord
- initForWord: (const char*) theWord fromVolume: (WebsterVolume*) volume
  andKeys: (websterKey *)theKeys number: (int)number;
{
  word = theWord;
  comesFrom = volume;
  keys = theKeys;
  numberOfKeys = number;
  definitions = NULL;
  return self;
}

- loadDataFromKeys
// Internal Function
{
  int i;
  // If already loaded,  ok
  if (definitions) return self;
  definitions = malloc(sizeof(void*) * numberOfKeys);
  defsLengths = malloc(sizeof(int) * numberOfKeys);
  if (!defsLengths || !definitions) return nil;
  for(i=0;i<numberOfKeys; i++) definitions[i] = NULL, defsLengths[i] = 0;
  for(i=1; i<numberOfKeys; i++) {
    IXBTreeCursor *cursor = [comesFrom getEntriesCursor];
    if ([cursor setKey: &keys[i] andLength:sizeof(keys[i])]) {
      const unsigned char* contents = NULL;
      int length = [cursor readValue: (void**)&contents];
      decodeEntry(contents, length, &definitions[i], &defsLengths[i]);
      free((char*)contents);
    } else return nil;
  }
  return self;
}

- outputDefinitionAs: (const char*) set result: (char **) where length: (int*) length
// Not yet implemented
{
  // Iterate all the definitions
  int i;
  NXStream* stream;
  int maxlen;

  if (![comesFrom canOutputDefinitionsAs: set]) return nil;

  if (!(stream = NXOpenMemory(NULL, 0, NX_WRITEONLY))) return nil;

  for(i=1; i<numberOfKeys; i++) {
    char* outi;
    int lengthi;
    if ([self outputDefinitionAs: set forDefNumber: i result: &outi length: &lengthi]) {
      // Concat this entry
      NXWrite(stream, outi, lengthi);
      vm_deallocate(task_self(), (vm_address_t)outi, (vm_size_t)lengthi);
    }
  }
  NXCloseMemory(stream, NX_TRUNCATEBUFFER);
  NXGetMemoryBuffer(stream, where, length, &maxlen);

  return self;
}

- outputDefinitionAs: (const char*) mode forDefNumber: (int) n 
  result: (char**) where length: (int*) length
{
  websterMode* m = [comesFrom getModeEntry: mode];
  if (n > numberOfKeys) return nil;
  if (m) {
    NXStream *stream = NULL;
    int maxlen;
    if (![self loadDataFromKeys]) return nil;
    m->translationFunc(definitions[n], defsLengths[n], word, &stream, m->select);
    if (!stream) return nil;
    NXCloseMemory(stream, NX_TRUNCATEBUFFER);
    NXGetMemoryBuffer(stream, where, length, &maxlen);
    return self;
  } else return nil;
}

- (int) numberOfDefinitions
{
  return numberOfKeys-1;
}

- (const char*) word
{
  return word;
}

- free
{
  if (keys) free(keys), keys = NULL;
  if (definitions && defsLengths) {
    int i;
    for(i=0; i<numberOfKeys; i++) 
      if (definitions[i]) free(definitions[i]), definitions[i] = NULL;
  }
  if (definitions) free(definitions), definitions = NULL;
  if (defsLengths) free(defsLengths), defsLengths = NULL;
  if (word) free((char *)word), word = NULL;
  return [super free];
}

@end
