/* Copyright (C) 1996,1997 Robert H”hne, see COPYING.RH for details */
/* This file is part of RHIDE. */
#define Uses_TWindow
#define Uses_TProgram
#define Uses_TDeskTop
#define Uses_TDialog
#define Uses_TScrollBar
#define Uses_TWindowList
#define Uses_TSCollection
#define Uses_tvutilCommands
#define Uses_tvutilFunctions
#include <libtvuti.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

TSCollection *windows=NULL;

#define WHERE TProgram::deskTop

class TWindowWatcher : public TView
{
public:
  TWindowWatcher();
  virtual void handleEvent(TEvent &);
};

TWindowWatcher *windowwatcher;

TWindowWatcher::TWindowWatcher() : TView(TRect(0,0,1,1))
{
  options |= ofPreProcess;
}

void TWindowWatcher::handleEvent(TEvent & event)
{
  if (owner->phase != phPreProcess) return;
  if (event.what == evCommand && event.message.command == cmClose)
  {
    TWindow *window = (TWindow *)TProgram::deskTop->current;
    int found = 0;
    int i;
    for (i=0;i<windows->getCount();i++)
    {
      if (window == DESKTOPWINDOW(i))
      {
        found = 1;
        break;
      }
    }
    if (!found) return;
    clearEvent(event);
    if (window->valid(cmClose) == True)
    {
      RemoveWindow(window);
      window->close();
      return;
    }
  }
}

static char *numbers = 0;
static int numbers_count = 0;
static int numbers_size = 0;
#define numbers_block_size 120

void AddWindow(TWindow *window,TWindow **ref,Boolean before)
{
  int i,count,Number;
  DeskTopWindow *window_rec;
  if (!windows)
  {
    windows = new TSCollection();
    TProgram::deskTop->insert((windowwatcher = new TWindowWatcher()));
    windowwatcher->hide();
  }
  count = windows->getCount();
  Number = -1;
  for (i=0;i<numbers_count;i++)
  {
    if (!numbers[i])
    {
      Number = i;
      numbers[i] = 1;
      break;
    }
  }
  if (Number == -1)
  {
    if (numbers_count >= numbers_size)
    {
      numbers_size += numbers_block_size;
      numbers = (char *)realloc(numbers,sizeof(char)*numbers_size);
    }
    numbers[i] = 1;
    Number = numbers_count;
    numbers_count++;
  }
  window->number = Number + 1;
  window_rec = new DeskTopWindow;
  window_rec->window = window;
  window_rec->ref = ref;
  window_rec->full_name = strdup(window->getTitle(1000));
  BaseName(window_rec->full_name,window_rec->base_name);
  windows->insert(window_rec);
  if (before == True)
    WHERE->insertBefore(window, WHERE->last);
  else 
    WHERE->insert(window);
}

void UpdateWindow(TWindow *window)
{
  int i,count;
  if (!windows) return;
  if (!window) return;
  count = windows->getCount();
  for (i=0;i<count;i++)
  {
    DeskTopWindow *w = (DeskTopWindow *)windows->at(i);
    if (w->window == window)
    {
      string_free(w->full_name);
      string_free(w->base_name);
      string_dup(w->full_name,window->getTitle(1000));
      BaseName(w->full_name,w->base_name);
    }
  }
}

void RemoveWindow(TWindow *window)
{
  int i,count;
  if (!windows) return;
  if (!window) return;
  count = windows->getCount();
  for (i=0;i<count;i++)
  {
    DeskTopWindow *w = (DeskTopWindow *)windows->at(i);
    if (w->window == window)
    {
      numbers[window->number-1] = 0;
      windows->atRemove(i);
      string_free(w->full_name);
      string_free(w->base_name);
      if (w->ref) *(w->ref) = NULL;
      delete(w);
      return;
    }   
  }
}

void ShowWindowList(const char *title)
{
  TDialog *dialog;
  TWindowList *list;
  TScrollBar *scrollbar;
  int i;
  TWindow *window;
  dialog = new TDialog(TRect(0,0,75,16),title);
  dialog->options |= ofCentered;
  scrollbar = new TScrollBar(TRect(72,1,73,14));
  list = new TWindowList(TRect(1,1,72,14),1,scrollbar);
  list->newList(windows);
  dialog->insert(list);
  dialog->insert(scrollbar);
  do
  {
    TProgram::deskTop->insert(dialog);
    dialog->setState(sfModal,True);
    i = dialog->execute();
    TProgram::deskTop->remove(dialog);
    switch (i)
    {
      case cmSelectWindow:
        if (list->range == 0) break;
        window = DESKTOPWINDOW(list->focused);
        window->select();
        window->show();
        i = cmCancel;
        break;
      case cmDeleteWindow:
      {
        if (list->range == 0) break;
        window = DESKTOPWINDOW(list->focused);
        if (window->valid(cmClose) == True)
        {
          RemoveWindow(window);
          destroy(window);
          list->newList(windows);
        }
        break;
      }
      default:
        i = cmCancel;
    }
  } while (i != cmCancel);
  destroy(dialog);
}
