This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-goldedplus/goldlib/gcui/gwinpick.cpp

529 lines
12 KiB
C++

// This may look like C code, but it is really -*- C++ -*-
// ------------------------------------------------------------------
// The Goldware Library
// Copyright (C) 1990-1999 Odinn Sorensen
// Copyright (C) 1999-2000 Alexander S. Aganichev
// ------------------------------------------------------------------
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this program; if not, write to the Free
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
// MA 02111-1307, USA
// ------------------------------------------------------------------
// $Id$
// ------------------------------------------------------------------
// GCUI: Golded+ Character-oriented User Interface.
// Class gwinpick - Pick engine.
// ------------------------------------------------------------------
#include <gkbdcode.h>
#include <gmoubase.h>
#include <gtimall.h>
#include <gutlmisc.h>
#include <gwinall.h>
#include <gwinhelp.h>
#include <gwinpick.h>
// ------------------------------------------------------------------
gwinpick::gwinpick() {
// memset(this, 0, sizeof(gwinpick)); WHAT!?!?! ARE YOU NUTS?
key = 0;
keyok = false;
ypos = xpos = ylen = xlen = 0;
btype = 0;
battr = wattr = tattr = sattr = hattr = loattr = sbattr = BLACK_|_BLACK;
title = NULL;
helpcat = 0;
maximum_index = minimum_index = maximum_position = index = position = 0;
aborted = listwrap = false;
direction = 0;
replylinkfloat = 0;
}
// ------------------------------------------------------------------
void gwinpick::cursor_up() {
bool done;
do {
if(index > minimum_index) {
display_line();
if(position)
position--;
else
scroll(SDOWN);
index--;
if((done = is_selectable(index))==true)
update_cursor();
}
else {
if(listwrap)
cursor_last();
else if(not is_selectable(index))
cursor_down();
done = true;
}
} while(not done);
direction = -1;
}
// ------------------------------------------------------------------
void gwinpick::cursor_down() {
bool done;
do {
if(index < maximum_index) {
display_line();
index++;
if(position < maximum_position)
position++;
else
scroll(SUP);
if((done = is_selectable(index))!=false)
update_cursor();
}
else {
if(listwrap)
cursor_first();
else if(not is_selectable(index))
cursor_up();
done = true;
}
} while(not done);
direction = 1;
}
// ------------------------------------------------------------------
void gwinpick::cursor_pageup() {
uint i = index - position;
while(not is_selectable(i)) i++;
uint min = i + position - index;
if(position > min) {
display_line();
index = i;
position = min;
update_cursor();
}
else if(index > min) {
i = maximum_position - min + position;
index -= (index >= i) ? i : index;
position = 0;
display_page();
if(not is_selectable(index))
cursor_down();
}
direction = -1;
}
// ------------------------------------------------------------------
void gwinpick::cursor_pagedown() {
uint max_index = index + maximum_position - position;
if(max_index > maximum_index) max_index = maximum_index;
while(not is_selectable(max_index)) --max_index;
uint max_position = max_index - index + position;
if(position < max_position) {
if(index == max_index) {
if(maximum_position < maximum_index) {
position = maximum_position;
index = maximum_index;
display_page();
update_cursor();
}
}
else if(max_index >= max_position) {
display_line();
position = max_position;
index = max_index;
update_cursor();
}
else if(position != maximum_position) {
display_line();
index += maximum_position-position;
position = maximum_position;
update_cursor();
}
}
else if(index < maximum_index) {
if(index+maximum_position+(maximum_position - max_position)> maximum_index) {
position = maximum_index - index;
index = maximum_index;
}
else {
index += maximum_position + (maximum_position - max_position);
position = maximum_position;
}
display_page();
}
if(not is_selectable(index))
cursor_up();
direction = 1;
}
// ------------------------------------------------------------------
void gwinpick::cursor_first() {
uint min_select = minimum_index;
while(not is_selectable(min_select))
min_select++;
if(index > min_select) {
if(index <= position) {
display_line();
index = position = min_select;
update_cursor();
}
else {
index = position = min_select;
display_page();
}
}
direction = -1;
}
// ------------------------------------------------------------------
void gwinpick::cursor_last() {
uint max_select = maximum_index;
while(not is_selectable(max_select))
max_select--;
if(index < max_select) {
if(index + (maximum_position-position) >= maximum_index) {
display_line();
position += max_select - index;
index = max_select;
update_cursor();
}
else {
position = (maximum_index-index) < maximum_position ? maximum_index-index : maximum_position;
position -= maximum_index - max_select;
index = max_select;
display_page();
}
}
else if(position < maximum_position) {
if(maximum_position < maximum_index) {
position = maximum_position + max_select - maximum_index;
index = max_select;
display_page();
}
}
direction = 1;
}
// ------------------------------------------------------------------
void gwinpick::cursor_scroll_up() {
uint oldidx = index;
do {
if(index - position)
index--;
else
while((not is_selectable(index)) and (index < maximum_index))
index++;
} while(not is_selectable(index));
if(index != oldidx)
display_page();
direction = -1;
}
// ------------------------------------------------------------------
void gwinpick::cursor_scroll_down() {
uint oldidx = index;
if(index != maximum_index) {
do {
if(index < maximum_index)
index++;
else
while((not is_selectable(--index)) and (index > minimum_index))
;
} while(not is_selectable(index));
}
if(index!=oldidx)
display_page();
direction = 1;
}
// ------------------------------------------------------------------
void gwinpick::display_line(bool bar) {
print_line(index, position, bar);
}
// ------------------------------------------------------------------
void gwinpick::display_page() {
if(index > position)
index -= position;
else
index = 0;
register uint m = maximum_index-index;
uint n;
if (replylinkfloat)
{
if (h_offset == new_hoffset)
{
for (n=0; n<=maximum_position and n<=m; n++)
if (position == n)
print_line(index+n, n, true);
}
h_offset = new_hoffset;
}
for(n=0; n<=maximum_position and n<=m; n++)
print_line(index+n, n, (position == n));
if(n < ylen)
wputx(n, 0, battr|ACSET, _box_table(btype,1), xlen);
for(++n; n<ylen; n++)
wputx(n, 0, wattr, (vchar)' ', xlen);
index += position;
wgotoxy(position, 0);
}
// ------------------------------------------------------------------
void gwinpick::open() { update(); }
void gwinpick::close() {}
void gwinpick::precursor() {}
void gwinpick::do_delayed() {}
void gwinpick::scroll(int direction) { wscroll(1, direction); }
bool gwinpick::handle_key() { return false; }
bool gwinpick::is_selectable(uint) { return true; }
// ------------------------------------------------------------------
bool gwinpick::default_handle_key() {
keyok = true;
switch(key) {
case Key_Up: precursor(); cursor_up(); break;
case Key_Dwn: precursor(); cursor_down(); break;
case Key_PgUp: precursor(); cursor_pageup(); break;
case Key_PgDn: precursor(); cursor_pagedown(); break;
case Key_Home: precursor(); cursor_first(); break;
case Key_End: precursor(); cursor_last(); break;
case Key_C_Up: precursor(); cursor_scroll_up(); break;
case Key_C_Dwn: precursor(); cursor_scroll_down(); break;
default:
keyok = handle_key();
}
return keyok;
}
// ------------------------------------------------------------------
void gwinpick::update_cursor() {
wgotoxy(position, 0);
display_bar();
// do_delayed();
}
// ------------------------------------------------------------------
void gwinpick::center(int listmode) {
if(maximum_index <= maximum_position) {
position = index;
update();
return;
}
uint botroom = maximum_index - index;
switch(listmode) {
case LIST_TOP:
position = (botroom > maximum_position) ? 0 : (maximum_position - botroom);
break;
case LIST_NEARTOP:
{
uint room;
uint toproom = index;
if(toproom > (maximum_position/4)) {
if(botroom > (maximum_position/4))
room = maximum_position/4;
else if(botroom)
room = maximum_position - botroom;
else
room = maximum_position;
}
else
room = toproom;
position = room;
}
break;
case LIST_MIDDLE:
{
uint room;
uint toproom = index;
if(toproom > (maximum_position/2)) {
if(botroom > (maximum_position/2))
room = maximum_position/2;
else if(botroom)
room = maximum_position - botroom;
else
room = maximum_position;
}
else
room = toproom;
position = room;
}
break;
case LIST_NEARBOTTOM:
{
uint room;
uint toproom = index;
if(toproom > 3*(maximum_position/4)) {
if(botroom > 3*(maximum_position/4))
room = 3*(maximum_position/4);
else if(botroom)
room = maximum_position - botroom;
else
room = maximum_position;
}
else
room = toproom;
position = room;
}
break;
case LIST_BOTTOM:
position = maximum_position;
break;
}
update();
}
// ------------------------------------------------------------------
int gwinpick::run_picker() {
#ifdef GOLD_MOUSE
gmou.HideCursor();
#endif
// Open and initialize
open();
if(helpcat)
whelppcat(helpcat);
if(not is_selectable(index))
cursor_down();
do {
do_delayed();
#ifdef GOLD_MOUSE
gmou.ShowCursor();
#endif
keyok = true;
do {
key = getxchtick();
if(key == Key_Tick)
handle_key();
} while(key == Key_Tick);
#ifdef GOLD_MOUSE
gmou.HideCursor();
#endif
keyok = default_handle_key();
if (replylinkfloat && (h_offset != new_hoffset))
display_page();
} while(keyok);
#ifdef GOLD_MOUSE
gmou.HideCursor();
#endif
// Close and clean
if(helpcat)
whelpop();
close();
#ifdef GOLD_MOUSE
gmou.ShowCursor();
#endif
return 0;
}
// ------------------------------------------------------------------