Revision 64 (by gdshaw@RISCPKG.ORG, 2007/05/21 05:44:33) Disabled exceptions and enabled optimisation to reduce code size.
// This file is part of the free Filer module for RISC OS.
// Copyright � 2007 Graham Shaw.
// Redistribution and modification are permitted under the terms of the
// GNU General Public License (version 2 or any later version).

#include <new>

#include "oslib/os.h"
#include "oslib/wimp.h"

#include "layout_method.h"
#include "filer_window.h"
#include "filer_application.h"
#include "main.h"

static wimp_MESSAGE_LIST(1) messages={0};

filer_application::filer_application():
	application("Filer",(wimp_message_list*)&messages),
	_auto_pos(0,0,0,0,1),
	_rename_window(0),
	_rename_icon(0),
	_rename_index(0)
{
	handle_mode_change();
}

void filer_application::handle_key_pressed(wimp_key& block)
{
	bool handled=false;
	if (_rename_window&&block.w==_rename_window->handle()&&
		block.i==_rename_icon)
	{
		// Keypress occurred within rename icon.
		if (block.c=='\r'||block.c=='\n')
		{
			// Keypress was carriage return or newline.
			_rename_window->rename(_rename_index,_rename_buffer);
			cancel_rename();
			handled=true;
		}
		else if (block.c==0x1b)
		{
			// Keypress was escape.
			cancel_rename();
			handled=true;
		}
	}

	// If not handled above then pass on the keypress.
	if (!handled) application::handle_key_pressed(block);
}

void filer_application::handle_pollword_non_zero(int* pollword)
{
	*pollword=0;
	pathnames.refresh();
}

void filer_application::handle_user_message(wimp_event_no event,
	wimp_message& message)
{
	switch (message.action)
	{
	case message_FILER_OPEN_DIR:
		handle_filer_open_dir(
			(filer_full_message_open_dir&)message);
		break;
	}
}

void filer_application::deregister_window(window& w)
{
	if (_rename_window==&w)
	{
		// Rename operation in progress within the window.
		// This must be cancelled, but there is no need to explicitly
		// delete the icon because the whole window is to be destroyed.
		_rename_window=0;
		_rename_icon=-1;
		_rename_index=directory::npos;
	}

	application::deregister_window(w);
}

void filer_application::handle_filer_open_dir(
	filer_full_message_open_dir& message)
{
	// Use auto-positioner to choose location for window.
	os_coord pos=_auto_pos();
	os_box box;
	box.x0=pos.x;
	box.y0=pos.y;
	box.x1=pos.x;
	box.y1=pos.y;

	// Open new filer window.
	new(std::nothrow) filer_window(
		this,message.dir_name,box,get_default_options());
}

void filer_application::handle_mode_change()
{
	// Get size of screen in pixels (less one).
	int xpixels;
	int ypixels;
	os_read_mode_variable(os_CURRENT_MODE,os_MODEVAR_XWIND_LIMIT,&xpixels);
	os_read_mode_variable(os_CURRENT_MODE,os_MODEVAR_YWIND_LIMIT,&ypixels);

	// Get eigenvalues.
	int xeig;
	int yeig;
	os_read_mode_variable(os_CURRENT_MODE,os_MODEVAR_XEIG_FACTOR,&xeig);
	os_read_mode_variable(os_CURRENT_MODE,os_MODEVAR_YEIG_FACTOR,&yeig);

	// Calculate size of screen in OS units.
	int xsize=(xpixels+1)<<xeig;
	int ysize=(ypixels+1)<<yeig;

	// Calculate number of steps.
	int step_size=128;
	int steps=xsize/(step_size*2);

	// Re-initialise automatic window positioner.
	_auto_pos=auto_pos(0,3*ysize/4,step_size,0,steps);
}

void filer_application::begin_rename(filer_window& w,
	directory::size_type index,os_coord pos)
{
	cancel_rename();
	_rename_index=index;
	_rename_icon=w.open_rename(index,pos,_rename_buffer);
	_rename_window=&w;
}

void filer_application::cancel_rename()
{
	if (_rename_window)
	{
		_rename_window->close_rename(_rename_icon,_rename_index);
		_rename_window=0;
		_rename_icon=-1;
		_rename_index=directory::npos;
	}
}

pathname_table::node* filer_application::register_pathname(filer_window& w)
{
	return pathnames.insert(&w);
}

void filer_application::deregister_pathname(pathname_table::node* n)
{
	pathnames.erase(n);
}