Files
Vangers/surmap/sqimenu.cpp
2021-01-15 13:39:30 +07:00

555 lines
13 KiB
C++

/*
Simple-Quick Interface by K-Division::KranK
All Rights Reserved (C)1995
(Menu)
*/
#include "..\global.h"
#pragma hdrstop
#include "sqint.h"
/* ---------------------------- EXTERN SECTION ----------------------------- */
/* --------------------------- PROTOTYPE SECTION --------------------------- */
/* --------------------------- DEFINITION SECTION -------------------------- */
const int MAXSEEK = 32;
const int SEEKDELAY = 10;
sqMenuBar::sqMenuBar(unsigned char* s,sqPopupMenu* owner,int _status,int _value,int _rec)
{
int m = owner -> margin;
int sl = s?strlen((char*)s):0;
int l = sl + 2*m;
if(l > owner -> len) owner -> setlen(l);
else l = owner -> len;
data = new unsigned char[l + 1];
original_data = (unsigned char*)strdup((char*)s);
memset(data,' ',m);
if(s) memcpy(data + m,s,sl);
memset(data + m + sl,' ',l - sl - m);
data[l] = '\0';
if((status = _status) != 0) *data = 4;
value = _value;
rec = _rec;
}
void sqMenuBar::replace(sqPopupMenu* owner,unsigned char* s)
{
int m = owner -> margin;
int sl = s?strlen((char*)s):0;
int l = sl + 2*m;
if(l > owner -> len){
owner -> setlen(l);
delete data;
data = new unsigned char[l + 1];
}
else
l = owner -> len;
if(s) memcpy(data + m,s,sl);
memset(data + m + sl,' ',l - sl - m);
data[l] = '\0';
}
sqPopupMenu::sqPopupMenu(sqElem* _owner,int _x,int _y,int _visibars,sqFont* _font,int _len0,int _margin)
{
owner = _owner;
x = _x; y = _y;
sx = sy = 0;
visibars = _visibars;
margin = _margin;
font = _font;
len = len0 = _len0;
if(_len0) sx = _len0*_font -> sx, set();
maxbars = topbar = nbar = seekcounter = 0;
first = pointer = insert = NULL;
seeklen = 0;
seekbuf = new unsigned char[MAXSEEK + 1];
}
sqPopupMenu& sqPopupMenu::operator* (sqMenuBar* obj)
{
if(!first){
first = pointer = obj;
first -> next = first -> prev = NULL;
}
else {
obj -> prev = insert;
if(insert){
obj -> next = insert -> next;
if(insert -> next) insert -> next -> prev = obj;
insert -> next = obj;
}
else {
obj -> next = first;
first -> prev = obj;
first = obj;
}
}
insert = obj;
maxbars++;
sy = MIN(maxbars,visibars)*font -> sy; set(height);
return *this;
}
void sqPopupMenu::disconnect(sqMenuBar* obj,sqMenuBar** del)
{
if(obj == insert)
if(obj -> next) insert = obj -> next;
else insert = obj -> prev;
if(obj == first){
if(obj -> next) obj -> next -> prev = NULL;
first = obj -> next;
}
else {
obj -> prev -> next = obj -> next;
if(obj -> next) obj -> next -> prev = obj -> prev;
}
if(!del)
delete obj;
else {
obj -> next = *del;
*del = obj;
}
maxbars--;
sy = MIN(maxbars,visibars)*font -> sy; set(height);
}
void sqPopupMenu::setlen(int l)
{
sqMenuBar* p = first;
unsigned char* s;
if(l > len)
while(p){
s = new unsigned char[l + 1];
memcpy(s,p -> data,len);
memset(s + len,' ',l - len);
s[l] = '\0';
delete p -> data;
p -> data = s;
p = p -> next;
}
else
if(l < len)
while(p){
p -> data[l] = '\0';
p = p -> next;
}
len = l;
sx = len*font -> sx; set(height);
}
void sqPopupMenu::draw(int self)
{
nbar = getptr(pointer);
sqMenuBar* p = getbar(topbar);
int i = y,j = 0;
while(p && j < visibars){
if(p == pointer)
font -> draw(getX() + x,getY() + i,p -> data,SQ_SYSCOLOR,SQ_SYSCOLOR + 6 + (2 - height));
else
font -> draw(getX() + x,getY() + i,p -> data,SQ_SYSCOLOR,SQ_SYSCOLOR + 5);
i += font -> sy; j++;
p = p -> next;
}
sqElem::draw();
owner -> message(M_CHANGEOPTION);
}
sqMenuBar* sqPopupMenu::getbar(int n)
{
sqMenuBar* p = first;
while(p){
if(!n) return p;
p = p -> next;
n--;
}
return NULL;
}
int sqPopupMenu::getptr(sqMenuBar* b)
{
sqMenuBar* p = first;
int i = 0;
while(p){
if(p == b) return i;
p = p -> next;
i++;
}
return 0;
}
void sqPopupMenu::keytrap(int key)
{
switch(key){
case VK_TAB:
if(XKey.Pressed(VK_SHIFT))
owner -> message(M_PREVOBJ);
else
owner -> message(M_NEXTOBJ);
seeklen = 0;
break;
case VK_F7:
case VK_INSERT:
owner -> message(M_INSERT);
break;
case VK_F8:
case VK_DELETE:
owner -> message(M_DELETE);
break;
case VK_SPACE:
owner -> message(M_SETOPTION);
break;
case VK_RETURN:
if(XKey.Pressed(VK_SHIFT)){
if(seeklen)
if(pointer -> next)
seek(pointer -> next);
else
seek(first);
}
else {
seeklen = 0;
owner -> message(M_CHOICE);
}
break;
case VK_RSHIFT:
sqInputString::rus = 1 - sqInputString::rus;
break;
case VK_UP:
if(!pointer -> prev){
pointer = getbar(maxbars - 1);
topbar = (maxbars >= visibars)?maxbars - visibars:0;
}
else {
if(pointer == getbar(topbar)) topbar--;
pointer = pointer -> prev;
}
draw();
seeklen = 0;
break;
case VK_DOWN:
if(!pointer -> next){
pointer = first;
topbar = 0;
}
else {
if(getptr(pointer) - topbar + 1 == visibars) topbar++;
pointer = pointer -> next;
}
draw();
seeklen = 0;
break;
case VK_HOME:
if(pointer){
pointer = first;
topbar = 0;
draw();
}
seeklen = 0;
break;
case VK_END:
if(pointer -> next){
pointer = getbar(maxbars - 1);
topbar = (maxbars >= visibars)?maxbars - visibars:0;
draw();
}
seeklen = 0;
break;
case VK_LEFT:
if(pointer != getbar(topbar)){
pointer = getbar(topbar);
draw();
}
seeklen = 0;
break;
case VK_RIGHT:
if(pointer != getbar(topbar + MIN(visibars,maxbars) - 1)){
pointer = getbar(topbar + MIN(visibars,maxbars) - 1);
draw();
}
seeklen = 0;
break;
case VK_PRIOR:
if(pointer){
topbar = getptr(pointer) - visibars;
if(topbar < 0) topbar = 0;
pointer = getbar(topbar);
draw();
}
seeklen = 0;
break;
case VK_NEXT:
if(pointer != getbar(maxbars - 1)){
topbar = getptr(pointer) + visibars;
if(topbar >= maxbars) topbar = maxbars - 1;
pointer = getbar(topbar);
topbar -= MIN(maxbars,visibars) - 1;
draw();
}
seeklen = 0;
break;
case VK_OEM_PLUS:
owner -> message(M_SETALL);
break;
case VK_OEM_MINUS:
owner -> message(M_UNSETALL);
break;
default:
if(CLOCK() - seekcounter > SEEKDELAY) seeklen = 0;
if(seeklen <= MAXSEEK){
seekbuf[seeklen++] = key; // !
seek(pointer);
seekcounter = CLOCK();
}
break;
}
}
void sqPopupMenu::handler(sqEvent* e)
{
int n;
sqMenuBar* pb;
switch(e -> code){
case E_LBMPRESS:
// if( XGR_MouseObj.GetLeftClip() != getX() + x + XGR_MouseObj.SizeX/2){
// XGR_MouseObj.SetClip(getX() + x + XGR_MouseObj.SizeX/2, getY() + y + XGR_MouseObj.SizeY/2, getX() + x + sx - XGR_MouseObj.SizeX/2, getY() + y + sy - XGR_MouseObj.SizeY/2);
// XGR_MouseObj.left = getX() + x + XGR_MouseObj.SizeX/2;
// XGR_MouseObj.top = getY() + y + XGR_MouseObj.SizeY/2;
// XGR_MouseObj.right = getX() + x + sx - XGR_MouseObj.SizeX/2;
// XGR_MouseObj.bottom = getY() + y + sy - XGR_MouseObj.SizeY/2;
// XGR_MouseObj.change();
// }
owner -> message(M_SETOBJ,this);
n = topbar + (e -> y - (getY() + y))/font -> sy;
if(n >= maxbars) n = maxbars - 1;
pb = pointer;
pointer = getbar(n);
if(XGR_MouseObj.LastPosY > XGR_MouseObj.PosY && topbar + visibars - 1 == getptr(pointer)){
if(pointer -> next){
topbar++;
pointer = pointer -> next;
}
}
else
if(XGR_MouseObj.LastPosY < XGR_MouseObj.PosY && topbar == getptr(pointer)){
if(pointer -> prev){
topbar--;
pointer = pointer -> prev;
}
}
if(pointer != pb) draw();
break;
case E_LBMUNPRESS:
// XGR_MouseObj.SetClip(sqScr -> x + XGR_MouseObj.SizeX/2, sqScr -> y + XGR_MouseObj.SizeY/2, sqScr -> x + sqScr -> sx - XGR_MouseObj.SizeX/2, sqScr -> y + sqScr -> sy - XGR_MouseObj.SizeY/2);
// XGR_MouseObj.left = sqScr -> x + XGR_MouseObj.SizeX/2;
// XGR_MouseObj.right = sqScr -> x + sqScr -> sx - XGR_MouseObj.SizeX/2;
// XGR_MouseObj.top = sqScr -> y + XGR_MouseObj.SizeY/2;
// XGR_MouseObj.bottom = sqScr -> y + sqScr -> sy - XGR_MouseObj.SizeY/2;
// XGR_MouseObj.change();
break;
case E_LBMDOUBLE:
owner -> message(M_SETOBJ,this);
n = topbar + (e -> y - (getY() + y))/font -> sy;
if(n >= maxbars) n = maxbars - 1;
pointer = getbar(n);
draw();
owner -> message(M_SETOPTION);
break;
}
}
void sqPopupMenu::activate(int force)
{
// QuantObj = this;
if(force) remove();
set(1);
if(force) draw();
}
void sqPopupMenu::deactivate(void)
{
remove();
set(2);
draw();
}
void sqPopupMenu::seek(sqMenuBar* p0,int force)
{
sqMenuBar* p = p0;
while(p){
if(!memicmp(p -> data + margin,seekbuf,seeklen)){
setpointer(p,force);
return;
}
p = p -> next;
}
p = first;
while(p != p0){
if(!memicmp(p -> data + margin,seekbuf,seeklen)){
setpointer(p,force);
return;
}
p = p -> next;
}
}
void sqPopupMenu::setpointer(sqMenuBar* p,int force)
{
int dif = getptr(pointer) - topbar;
pointer = p;
topbar = getptr(p) - dif;
if(topbar < 0) topbar = 0;
else topbar = MIN(topbar,maxbars - MIN(maxbars,visibars));
if(force) draw();
}
void sqPopupMenu::free(void)
{
sqMenuBar* p = first,*p0;
while(p){
p0 = p -> next;
delete p;
p = p0;
}
if(first){
maxbars = topbar = nbar = seekcounter = 0;
first = pointer = insert = NULL;
len = len0;
seeklen = 0;
}
}
sqMultiMenu::sqMultiMenu(sqElem* _owner,int _x,int _y,int _visibars,sqFont* _font,int _maxlen)
{
owner = _owner;
x = _x; y = _y;
maxlen = _maxlen;
sx = _maxlen*_font -> sx + 2;
sy = _font -> sy + 8 + _visibars*_font -> sy + 2;
set(0);
*this + (edit = new sqInputString(this,2,0,_font -> sx*(_maxlen + 1),_font,(unsigned char*)NULL,_maxlen));
*this + (list = new sqPopupMenu(this,2,_font -> sy + 8,_visibars,_font,_maxlen + 2));
obj = NULL;
deleted = NULL;
}
void sqMultiMenu::keytrap(int key)
{
obj -> keytrap(key);
}
void sqMultiMenu::activate(int force)
{
obj = list;
obj -> activate();
}
void sqMultiMenu::deactivate(void)
{
obj -> deactivate();
obj = NULL;
}
void sqMultiMenu::message(int code,sqElem* object)
{
sqMenuBar* p;
switch(code){
case M_NEXTOBJ:
obj -> deactivate();
if(obj == edit){
obj = list;
obj -> activate();
}
else
owner -> message(M_NEXTOBJ);
break;
case M_PREVOBJ:
obj -> deactivate();
if(obj == edit){
obj = list;
obj -> activate();
}
else
owner -> message(M_PREVOBJ);
break;
case M_SETOBJ:
if(object != obj){
if((obj == edit && object == list) || (obj == list && object == edit))
obj -> deactivate();
else
owner -> message(M_DEACTIVATE,this);
obj = object;
obj -> activate();
}
break;
case M_CHOICE:
if(obj == edit){
list -> pointer -> replace(list,edit -> str);
obj -> deactivate();
obj = list;
obj -> activate();
}
else {
obj -> deactivate();
obj = edit;
obj -> activate();
}
break;
case M_SETOPTION:
list -> pointer -> status = 1 - list -> pointer -> status;
if(list -> pointer -> status) *list -> pointer -> data = 4;
else *list -> pointer -> data = ' ';
list -> draw();
break;
case M_CHANGEOPTION:
edit -> setstr(list -> pointer -> data + list -> margin);
edit -> draw();
owner -> message(M_CHANGEOPTION);
break;
case M_DELETE:
if(list -> maxbars > 1){
if(list -> pointer -> next) list -> insert = list -> pointer -> next;
else list -> insert = list -> pointer -> prev;
list -> remove();
list -> disconnect(list -> pointer,&deleted);
list -> pointer = list -> insert;
list -> draw();
}
break;
case M_INSERT:
if(!edit -> insert) list -> insert = list -> pointer;
else list -> insert = list -> pointer -> prev;
*list * new sqMenuBar((unsigned char*)NULL,list);
list -> pointer = list -> insert;
list -> draw();
message(M_CHOICE);
break;
case M_SETALL:
p = list -> first;
while(p){
*p -> data = 4;
p -> status = 1;
p = p -> next;
}
list -> draw();
break;
case M_UNSETALL:
p = list -> first;
while(p){
*p -> data = ' ';
p -> status = 0;
p = p -> next;
}
list -> draw();
break;
}
}
void sqMultiMenu::restore(int _x,int _y,int _sx,int _sy)
{
XGR_Rectangle(_x,_y,_sx,_sy,SQ_SYSCOLOR + 4,SQ_SYSCOLOR + 4,XGR_FILLED);
}