/*
 * Copyright (c) 1992, The Geometry Center
 *                     University of Minnesota 
 *                     1300 South Second Street
 *                     Minneapolis, MN  55454
 *
 * email address: software@geom.umn.edu
 *
 * This software is copyrighted as noted above.  It may be freely copied,
 * modified, and redistributed, provided that the copyright notice is
 * preserved on all copies.
 *
 * There is no warranty or other guarantee of fitness for this software,
 * it is provided solely "as is".  Bug reports or fixes may be sent
 * to the authors, who may or may not act on them as they desire.
 *
 * You may not include this software in a program or other software product
 * without supplying the source, or without informing the end-user that the
 * source is available for no extra charge.
 *
 * If you modify this software, you should include a notice giving the
 * name of the person performing the modification, the date of modification,
 * and the reason for such modification.
 *
 *     The National Science and Technology Research Center for
 *      Computation and Visualization of Geometric Structures
 */

/* Generated by Interface Builder */

#import <objc/List.h>
#import <appkit/Form.h>
#import "LabelField.h"
#import "FullView.h"
#import "FormatView.h"
#import "Distributor.h"
#import <streams/streams.h>
#import <appkit/SavePanel.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

@implementation FullView

- initFrame:(const NXRect *)frameRect
{
  [super initFrame:frameRect];
  currentPage = -1;
  filename = NULL;
  viewList = [[List allocFromZone:[self zone]] init];
  return self;
}

- drawSelf: (NXRect *)dRects:(int)dCount
{
  if (currentPage == -1) return self;
  [[viewList objectAt:currentPage] moveTo:0:0];
  return self;
}

- prevNext:sender
{
  [self gotoPage: currentPage + (([[sender selectedCell] tag]) ? 1 : -1)];
  return self;
}

- formChanged:sender
{
  [self gotoPage: [pageForm intValueAt:0]-1];
  return self;
}

- gotoPage:(int) page
{
  id view;
  int rows, columns;
  [window makeFirstResponder:[subviews objectAt:0]];
  if (page < 0) page = 0;
  if (page >= [viewList count]) page = [viewList count] - 1;
  view = [viewList objectAt:page];
  [pageForm setIntValue:page+1 at:0];
  [pageText setIntValue:page+1];
  [view getDims :&rows :&columns];
  [dimensionsForm setIntValue:rows at:1];
  [dimensionsForm setIntValue:columns at:0];
  currentPage = page;
  [subviews empty];        /* Empty out list of subviews */
  [self addSubview:view];  /* Make this the only subview */
  [window makeFirstResponder:view];
  [view unselectBox];
  [window display];
  return self;
}

- addPage
{
  NXRect itsframe;
  id newFV;
  [self getBounds:&itsframe];
  newFV = [[FormatView allocFromZone:[self zone]]
	    initFrame:&itsframe];
  [viewList addObject:newFV];
  return self;
}

- newPage:sender
{
  [self addPage];
  [self gotoPage:[viewList count]-1];
  return self;
}

- setDims:sender
{
  id view = [self getCurrentView];
  id spill, spillab;
  [view updateDims:[dimensionsForm intValueAt:1] :[dimensionsForm intValueAt:0]
   :&spill :&spillab];
  if (spill)
    [self placeList:spill :spillab in:view];
  [window makeKeyAndOrderFront:self];
  return self;
}

- getCurrentView
{
  if (currentPage == -1)
    {
      [self addPage];
      currentPage = 0;
      [subviews empty];                         /* Empty out list of subviews */
      [self addSubview:[viewList objectAt:0]];  /* Make this the only subview */
    }
  return [viewList objectAt:currentPage];
}


- place:sender
{
  id newlist, lablist, spill, spillab, view = [self getCurrentView];

  /* Get new links */
  [view updateDims:[dimensionsForm intValueAt:1] :[dimensionsForm intValueAt:0]
   :&spill :&spillab];
  [distributor getNewList:[view get_squareLength] :&newlist :&lablist];
  if (spill)
    /* Put spilled links at beginning of newlist */
    {
      while ([spill count])
	{
	  [newlist insertObject: [spill removeObjectAt:0] at:0];
	  [lablist insertObject: [spillab removeObjectAt:0] at:0];
	}
      [spill free];
      [spillab free];
    }
//  [viewBox setContentView:view];
  return [self placeList:newlist :lablist in:view];
}

- placeList:newlist :lablist in:view
{
  int page;

  /* Place as many as possible on current page */
  [view place:newlist :lablist];

  /* Bump rest of links to next pages */
  for (page = currentPage+1; [newlist count]; page++)
    {
      if (page >= [viewList count]) [self addPage];
      [[viewList objectAt:page] place:newlist :lablist];
    }
  [window display];
  [window flushWindow];
  [window makeKeyAndOrderFront:self];
  return self;
}

/*** Printing enjoyments ***/

- (BOOL)getRect:(NXRect *)theRect forPage:(int)page
{
  if (page > [viewList count]) return NO;
  currentPage = page-1;
  *theRect = bounds;
  [subviews empty];
  [self addSubview:[viewList objectAt:currentPage]];
  return YES;
}

- (BOOL)knowsPagesFirst:(int *)firstPageNum last:(int *)lastPageNum
{
  oldCP = currentPage;
  if (*firstPageNum < 1) *firstPageNum = 1;
  if (*lastPageNum > [viewList count]) *lastPageNum = [viewList count];
  return YES;
}

- endPSOutput
{
  currentPage = oldCP;
  return [super endPSOutput];
}

/**** File operations ****/

- save
{
  if (filename == NULL) [self saveAs];
  else [self doSave];
  return self;
}

- saveAs
{
  id savepanel = [SavePanel new];
  int success;
  const char *tmpfile;
  [savepanel setAccessoryView:nil];
  [savepanel setTitle:([viewList count] < 2) ? "Save formatted page" :
   "Save formatted pages"];
  [savepanel setPrompt:"File:"];
  [savepanel setRequiredFileType:EXT_FORMAT];
  success = [savepanel runModal];
  tmpfile = [savepanel filename];
  if (!success)
    return self;
  if (filename)
    free(filename);
  filename = NXZoneMalloc([self zone], strlen(tmpfile)+1);
  strcpy(filename, tmpfile);
  [self doSave];
  return self;
}

- doSave
{
  NXStream *stream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  NXTypedStream *tstream = NXOpenTypedStream(stream, NX_WRITEONLY);
  [self saveList:tstream];
  NXCloseTypedStream(tstream);
  NXSaveToFile(stream, filename);
  NXCloseMemory(stream, NX_FREEBUFFER);
  return self;
}


/* Archiving */

- saveList: (NXTypedStream *) tstream
{
  NXWriteRootObject(tstream, viewList);
  [self gotoPage:currentPage];
  return self;
}

- openList: (NXTypedStream *) tstream :(const char *) filenm
{
  if (filename)
    free(filename);
  filename = NXZoneMalloc([self zone], strlen(filenm)+1);
  strcpy(filename, filenm);
  [viewList free];
  viewList = NXReadObject(tstream);
  currentPage = 0;
  [self gotoPage:currentPage];
  return self;
}
  
@end
