1233 lines
31 KiB
C++
1233 lines
31 KiB
C++
/* g_text.cpp
|
|
*
|
|
* Copyright (c) 1994-1996, Marko Macek
|
|
*
|
|
* You may distribute under the terms of either the GNU General Public
|
|
* License or the Artistic License, as specified in the README file.
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <signal.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "console.h"
|
|
#include "gui.h"
|
|
#include "c_mode.h"
|
|
#include "c_color.h"
|
|
|
|
#if defined(_DEBUG) && defined(MSVC) && defined(MSVCDEBUG)
|
|
#include <crtdbg.h>
|
|
|
|
#define new new( _CLIENT_BLOCK, __FILE__, __LINE__)
|
|
|
|
#endif //_DEBUG && MSVC && MSVCDEBUG
|
|
|
|
|
|
int ShowVScroll = 1;
|
|
int ShowHScroll = 1;
|
|
int ShowMenuBar = 1;
|
|
int ShowToolBar = 0;
|
|
unsigned long HaveGUIDialogs = 0; // no gui dialogs in text gui
|
|
|
|
GFrame *frames = 0;
|
|
GUI *gui = 0;
|
|
|
|
GView *MouseCapture = 0;
|
|
GView *FocusCapture = 0;
|
|
|
|
TEvent NextEvent = { 0 };
|
|
|
|
#define sfFocus 1
|
|
|
|
class UpMenu;
|
|
|
|
extern int ExecMainMenu(TEvent &E, char sub);
|
|
extern int ExecVertMenu(int x, int y, int id, TEvent &E, UpMenu *up);
|
|
|
|
class GViewPeer {
|
|
public:
|
|
GView *View;
|
|
int wX, wY, wW, wH, wState;
|
|
int cX, cY, cVisible, cStart, cEnd;
|
|
int sbVstart, sbVamount, sbVtotal, sbVupdate;
|
|
int sbHstart, sbHamount, sbHtotal, sbHupdate;
|
|
int SbVBegin, SbVEnd, SbHBegin, SbHEnd;
|
|
|
|
GViewPeer(GView *view, int XSize, int YSize);
|
|
~GViewPeer();
|
|
|
|
int ConPutBox(int X, int Y, int W, int H, PCell Cell);
|
|
int ConGetBox(int X, int Y, int W, int H, PCell Cell);
|
|
int ConPutLine(int X, int Y, int W, int H, PCell Cell);
|
|
int ConSetBox(int X, int Y, int W, int H, TCell Cell);
|
|
int ConScroll(int Way, int X, int Y, int W, int H, TAttr Fill, int Count);
|
|
|
|
int ConSetSize(int X, int Y);
|
|
int ConQuerySize(int *X, int *Y);
|
|
|
|
int ConSetCursorPos(int X, int Y);
|
|
int ConQueryCursorPos(int *X, int *Y);
|
|
int ConShowCursor();
|
|
int ConHideCursor();
|
|
int ConCursorVisible();
|
|
int ConSetCursorSize(int Start, int End);
|
|
|
|
int CaptureMouse(int grab);
|
|
int CaptureFocus(int grab);
|
|
|
|
int QuerySbVPos();
|
|
int SetSbVPos(int Start, int Amount, int Total);
|
|
int SetSbHPos(int Start, int Amount, int Total);
|
|
int ExpandHeight(int DeltaY);
|
|
|
|
int DrawScrollBar();
|
|
int UpdateCursor();
|
|
};
|
|
|
|
class GFramePeer {
|
|
public:
|
|
int fW, fH;
|
|
GFrame *Frame;
|
|
|
|
GFramePeer(GFrame *aFrame, int Width, int Height);
|
|
~GFramePeer();
|
|
|
|
int ConSetTitle(char *Title, char *STitle);
|
|
int ConGetTitle(char *Title, int MaxLen, char *STitle, int SMaxLen);
|
|
|
|
int ConSetSize(int X, int Y);
|
|
int ConQuerySize(int *X, int *Y);
|
|
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
GViewPeer::GViewPeer(GView *view, int XSize, int YSize) {
|
|
View = view;
|
|
wX = 0;
|
|
wY = 0;
|
|
wW = XSize;
|
|
wH = YSize;
|
|
sbVtotal = 0;
|
|
sbVstart = 0;
|
|
sbVamount = 0;
|
|
sbVupdate = 1;
|
|
sbHtotal = 0;
|
|
sbHstart = 0;
|
|
sbHamount = 0;
|
|
sbHupdate = 1;
|
|
wState = 0;
|
|
cVisible = 1;
|
|
cStart = 0; // %
|
|
cEnd = 100;
|
|
cX = cY = 0;
|
|
}
|
|
|
|
GViewPeer::~GViewPeer() {
|
|
if (MouseCapture == View)
|
|
MouseCapture = 0;
|
|
if (FocusCapture == View)
|
|
FocusCapture = 0;
|
|
}
|
|
|
|
int GViewPeer::ConPutBox(int X, int Y, int W, int H, PCell Cell) {
|
|
return ::ConPutBox(X + wX, Y + wY, W, H, Cell);
|
|
}
|
|
|
|
int GViewPeer::ConGetBox(int X, int Y, int W, int H, PCell Cell) {
|
|
return ::ConGetBox(X + wX, Y + wY, W, H, Cell);
|
|
}
|
|
|
|
int GViewPeer::ConPutLine(int X, int Y, int W, int H, PCell Cell) {
|
|
return ::ConPutLine(X + wX, Y + wY, W, H, Cell);
|
|
}
|
|
|
|
int GViewPeer::ConSetBox(int X, int Y, int W, int H, TCell Cell) {
|
|
return ::ConSetBox(X + wX, Y + wY, W, H, Cell);
|
|
}
|
|
|
|
int GViewPeer::ConScroll(int Way, int X, int Y, int W, int H, TAttr Fill, int Count) {
|
|
return ::ConScroll(Way, X + wX, Y + wY, W, H, Fill, Count);
|
|
}
|
|
|
|
int GViewPeer::ConSetSize(int X, int Y) {
|
|
wW = X;
|
|
wH = Y;
|
|
return 1;
|
|
}
|
|
|
|
int GViewPeer::ConQuerySize(int *X, int *Y) {
|
|
if (X) *X = wW;
|
|
if (Y) *Y = wH;
|
|
return 1;
|
|
}
|
|
|
|
int GViewPeer::ConSetCursorPos(int X, int Y) {
|
|
if (X < 0) X = 0;
|
|
if (X >= wW) X = wW - 1;
|
|
if (Y < 0) Y = 0;
|
|
if (Y >= wH) Y = wH - 1;
|
|
cX = X;
|
|
cY = Y;
|
|
if (wState & sfFocus)
|
|
return ::ConSetCursorPos(cX + wX, cY + wY);
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
int GViewPeer::ConQueryCursorPos(int *X, int *Y) {
|
|
if (X) *X = cX;
|
|
if (Y) *Y = cY;
|
|
return 1;
|
|
}
|
|
|
|
int GViewPeer::ConShowCursor() {
|
|
cVisible = 1;
|
|
if (wState & sfFocus)
|
|
return ::ConShowCursor();
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
int GViewPeer::ConHideCursor() {
|
|
cVisible = 0;
|
|
if (wState & sfFocus)
|
|
return ::ConHideCursor();
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
int GViewPeer::ConCursorVisible() {
|
|
return cVisible;
|
|
}
|
|
|
|
int GViewPeer::ConSetCursorSize(int Start, int End) {
|
|
cStart = Start;
|
|
cEnd = End;
|
|
if (wState & sfFocus)
|
|
return ::ConSetCursorSize(Start, End);
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
int GViewPeer::CaptureMouse(int grab) {
|
|
if (MouseCapture == 0) {
|
|
if (grab)
|
|
MouseCapture = View;
|
|
else
|
|
return 0;
|
|
} else {
|
|
if (grab || MouseCapture != View)
|
|
return 0;
|
|
else
|
|
MouseCapture = 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int GViewPeer::CaptureFocus(int grab) {
|
|
if (FocusCapture == 0) {
|
|
if (grab)
|
|
FocusCapture = View;
|
|
else
|
|
return 0;
|
|
} else {
|
|
if (grab || FocusCapture != View)
|
|
return 0;
|
|
else
|
|
FocusCapture = 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int GViewPeer::ExpandHeight(int DeltaY) {
|
|
if (View->Parent->Top == View->Next)
|
|
return -1;
|
|
if (DeltaY + wH < 3)
|
|
DeltaY = - (wH - 3);
|
|
if (View->Next->Peer->wH - DeltaY < 3)
|
|
DeltaY = View->Next->Peer->wH - 3;
|
|
View->Peer->ConSetSize(wW, wH + DeltaY);
|
|
View->Next->Peer->wY += DeltaY;
|
|
View->Next->Peer->ConSetSize(View->Next->Peer->wW, View->Next->Peer->wH - DeltaY);
|
|
View->Resize(View->Peer->wW, View->Peer->wH);
|
|
View->Next->Resize(View->Next->Peer->wW, View->Next->Peer->wH);
|
|
return 0;
|
|
}
|
|
|
|
int GViewPeer::QuerySbVPos() {
|
|
return sbVstart;
|
|
}
|
|
|
|
int GViewPeer::SetSbVPos(int Start, int Amount, int Total) {
|
|
if (sbVstart != Start ||
|
|
sbVamount != Amount ||
|
|
sbVtotal != Total)
|
|
{
|
|
sbVstart = Start;
|
|
sbVamount = Amount;
|
|
sbVtotal = Total;
|
|
sbVupdate = 1;
|
|
// DrawScrollBar();
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int GViewPeer::SetSbHPos(int Start, int Amount, int Total) {
|
|
if (sbHstart != Start ||
|
|
sbHamount != Amount ||
|
|
sbHtotal != Total)
|
|
{
|
|
sbHstart = Start;
|
|
sbHamount = Amount;
|
|
sbHtotal = Total;
|
|
sbHupdate = 1;
|
|
// DrawScrollBar();
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int GViewPeer::UpdateCursor() {
|
|
ConSetCursorPos(cX, cY);
|
|
ConSetCursorSize(cStart, cEnd);
|
|
if (cVisible)
|
|
ConShowCursor();
|
|
else
|
|
ConHideCursor();
|
|
return 0;
|
|
}
|
|
|
|
int GViewPeer::DrawScrollBar() {
|
|
TDrawBuffer B;
|
|
int NRows, NCols, I;
|
|
int W, H;
|
|
char fore = ConGetDrawChar(DCH_HFORE);
|
|
char back = ConGetDrawChar(DCH_HBACK);
|
|
|
|
ConQuerySize(&W, &H);
|
|
|
|
if (ShowVScroll) {
|
|
MoveCh(B, ConGetDrawChar(DCH_AUP), hcScrollBar_Arrows, 1);
|
|
ConPutBox(W, 0, 1, 1, B);
|
|
MoveCh(B, ConGetDrawChar(DCH_ADOWN), hcScrollBar_Arrows, 1);
|
|
ConPutBox(W, H - 1, 1, 1, B);
|
|
|
|
NRows = H - 2;
|
|
|
|
if (sbVtotal <= NRows) {
|
|
SbVBegin = 0;
|
|
SbVEnd = NRows - 1;
|
|
} else {
|
|
SbVBegin = NRows * sbVstart / sbVtotal;
|
|
SbVEnd = SbVBegin + NRows * sbVamount / sbVtotal;
|
|
}
|
|
|
|
for (I = 0; I < NRows; I++) {
|
|
if (I >= SbVBegin && I <= SbVEnd)
|
|
MoveCh(B, fore, hcScrollBar_Fore, 1);
|
|
else
|
|
MoveCh(B, back, hcScrollBar_Back, 1);
|
|
ConPutBox(W, I + 1, 1, 1, B);
|
|
}
|
|
}
|
|
if (ShowHScroll) {
|
|
MoveCh(B, ConGetDrawChar(DCH_ALEFT), hcScrollBar_Arrows, 1);
|
|
ConPutBox(0, H, 1, 1, B);
|
|
MoveCh(B, ConGetDrawChar(DCH_ARIGHT), hcScrollBar_Arrows, 1);
|
|
ConPutBox(W - 1, H, 1, 1, B);
|
|
|
|
NCols = W - 2;
|
|
|
|
if (sbHtotal <= NCols) {
|
|
SbHBegin = 0;
|
|
SbHEnd = NCols - 1;
|
|
} else {
|
|
SbHBegin = NCols * sbHstart / sbHtotal;
|
|
SbHEnd = SbHBegin + NCols * sbHamount / sbHtotal;
|
|
}
|
|
|
|
// could be made faster
|
|
for (I = 0; I < NCols; I++) {
|
|
if (I >= SbHBegin && I <= SbHEnd)
|
|
MoveCh(B, fore, hcScrollBar_Fore, 1);
|
|
else
|
|
MoveCh(B, back, hcScrollBar_Back, 1);
|
|
ConPutBox(I + 1, H, 1, 1, B);
|
|
}
|
|
}
|
|
if (ShowVScroll && ShowHScroll) {
|
|
MoveCh(B, ' ', hcScrollBar_Arrows, 1);
|
|
ConPutBox(W, H, 1, 1, B);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
GView::GView(GFrame *parent, int XSize, int YSize) {
|
|
Parent = parent;
|
|
Prev = Next = 0;
|
|
Peer = new GViewPeer(this, XSize, YSize);
|
|
if (Parent)
|
|
Parent->AddView(this);
|
|
}
|
|
|
|
GView::~GView() {
|
|
if (Parent)
|
|
Parent->RemoveView(this);
|
|
delete Peer;
|
|
}
|
|
|
|
int GView::ConClear() {
|
|
int W, H;
|
|
TDrawBuffer B;
|
|
|
|
ConQuerySize(&W, &H);
|
|
MoveChar(B, 0, W, ' ', 0x07, 1);
|
|
ConSetBox(0, 0, W, H, B[0]);
|
|
return 1;
|
|
}
|
|
|
|
int GView::ConPutBox(int X, int Y, int W, int H, PCell Cell) {
|
|
return Peer->ConPutBox(X, Y, W, H, Cell);
|
|
}
|
|
|
|
int GView::ConGetBox(int X, int Y, int W, int H, PCell Cell) {
|
|
return Peer->ConGetBox(X, Y, W, H, Cell);
|
|
}
|
|
|
|
int GView::ConPutLine(int X, int Y, int W, int H, PCell Cell) {
|
|
return Peer->ConPutLine(X, Y, W, H, Cell);
|
|
}
|
|
|
|
int GView::ConSetBox(int X, int Y, int W, int H, TCell Cell) {
|
|
return Peer->ConSetBox(X, Y, W, H, Cell);
|
|
}
|
|
|
|
int GView::ConScroll(int Way, int X, int Y, int W, int H, TAttr Fill, int Count) {
|
|
return Peer->ConScroll(Way, X, Y, W, H, Fill, Count);
|
|
}
|
|
|
|
int GView::ConSetSize(int X, int Y) {
|
|
if (Peer->ConSetSize(X, Y))
|
|
Resize(X, Y);
|
|
else
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
int GView::ConQuerySize(int *X, int *Y) {
|
|
return Peer->ConQuerySize(X, Y);
|
|
}
|
|
|
|
int GView::ConSetCursorPos(int X, int Y) {
|
|
return Peer->ConSetCursorPos(X, Y);
|
|
}
|
|
|
|
int GView::ConQueryCursorPos(int *X, int *Y) {
|
|
return Peer->ConQueryCursorPos(X, Y);
|
|
}
|
|
|
|
int GView::ConShowCursor() {
|
|
return Peer->ConShowCursor();
|
|
}
|
|
|
|
int GView::ConHideCursor() {
|
|
return Peer->ConHideCursor();
|
|
}
|
|
|
|
int GView::ConCursorVisible() {
|
|
return Peer->ConCursorVisible();
|
|
}
|
|
|
|
int GView::ConSetCursorSize(int Start, int End) {
|
|
return Peer->ConSetCursorSize(Start, End);
|
|
}
|
|
|
|
int GView::CaptureMouse(int grab) {
|
|
return Peer->CaptureMouse(grab);
|
|
}
|
|
|
|
int GView::CaptureFocus(int grab) {
|
|
return Peer->CaptureFocus(grab);
|
|
}
|
|
|
|
int GView::QuerySbVPos() {
|
|
return Peer->QuerySbVPos();
|
|
}
|
|
|
|
int GView::SetSbVPos(int Start, int Amount, int Total) {
|
|
return Peer->SetSbVPos(Start, Amount, Total);
|
|
}
|
|
|
|
int GView::SetSbHPos(int Start, int Amount, int Total) {
|
|
return Peer->SetSbHPos(Start, Amount, Total);
|
|
}
|
|
|
|
int GView::ExpandHeight(int DeltaY) {
|
|
return Peer->ExpandHeight(DeltaY);
|
|
}
|
|
|
|
void GView::Update() {
|
|
}
|
|
|
|
void GView::Repaint() {
|
|
}
|
|
|
|
void GView::HandleEvent(TEvent &/*Event*/) {
|
|
}
|
|
|
|
void GView::Resize(int /*width*/, int /*height*/) {
|
|
Repaint();
|
|
}
|
|
|
|
void GView::EndExec(int NewResult) {
|
|
Result = NewResult;
|
|
}
|
|
|
|
int GView::Execute() {
|
|
int SaveRc = Result;
|
|
int NewResult;
|
|
int didFocus = 0;
|
|
|
|
if (FocusCapture == 0) {
|
|
if (CaptureFocus(1) == 0) return -1;
|
|
didFocus = 1;
|
|
} else
|
|
if (FocusCapture != this)
|
|
return -1;
|
|
Result = -2;
|
|
while (Result == -2 && frames != 0)
|
|
gui->ProcessEvent();
|
|
NewResult = Result;
|
|
Result = SaveRc;
|
|
if (didFocus)
|
|
CaptureFocus(0);
|
|
return NewResult;
|
|
}
|
|
|
|
int GView::IsActive() {
|
|
return (Parent->Active == this);
|
|
}
|
|
|
|
void GView::Activate(int gotfocus) {
|
|
if (gotfocus) {
|
|
Peer->wState |= sfFocus;
|
|
Peer->UpdateCursor();
|
|
} else {
|
|
Peer->wState &= ~sfFocus;
|
|
}
|
|
Repaint();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
GFramePeer::GFramePeer(GFrame *aFrame, int Width, int Height) {
|
|
Frame = aFrame;
|
|
if (Width != -1 && Height != -1)
|
|
ConSetSize(Width, Height);
|
|
ConQuerySize(&fW, &fH);
|
|
}
|
|
|
|
GFramePeer::~GFramePeer() {
|
|
}
|
|
|
|
int GFramePeer::ConSetSize(int X, int Y) {
|
|
return ::ConSetSize(X, Y);
|
|
}
|
|
|
|
int GFramePeer::ConQuerySize(int *X, int *Y) {
|
|
::ConQuerySize(&fW, &fH);
|
|
if (X) *X = fW;
|
|
if (Y) *Y = fH;
|
|
return 1;
|
|
}
|
|
|
|
//int GFrame::ConQuerySize(int *X, int *Y) {
|
|
// ::ConQuerySize(X, Y);
|
|
// if (ShowVScroll)
|
|
// --*X;
|
|
//}
|
|
|
|
int GFramePeer::ConSetTitle(char *Title, char *STitle) {
|
|
::ConSetTitle(Title, STitle);
|
|
return 0;
|
|
}
|
|
|
|
int GFramePeer::ConGetTitle(char *Title, int MaxLen, char *STitle, int SMaxLen) {
|
|
return ::ConGetTitle(Title, MaxLen, STitle, SMaxLen);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
GFrame::GFrame(int XSize, int YSize) {
|
|
Menu = 0;
|
|
if (frames == 0) {
|
|
frames = Prev = Next = this;
|
|
} else {
|
|
Next = frames->Next;
|
|
Prev = frames;
|
|
frames->Next->Prev = this;
|
|
frames->Next = this;
|
|
frames = this;
|
|
}
|
|
Top = Active = 0;
|
|
Peer = new GFramePeer(this, XSize, YSize);
|
|
}
|
|
|
|
GFrame::~GFrame() {
|
|
if (Peer) {
|
|
delete Peer;
|
|
Peer = 0;
|
|
}
|
|
if (Next == this) {
|
|
frames = 0;
|
|
// printf("No more frames\x7\x7\n");
|
|
} else {
|
|
Next->Prev = Prev;
|
|
Prev->Next = Next;
|
|
frames = Next;
|
|
}
|
|
Next = Prev = 0;
|
|
if (Menu)
|
|
free(Menu);
|
|
}
|
|
|
|
int GFrame::ConSetTitle(char *Title, char *STitle) {
|
|
return Peer->ConSetTitle(Title, STitle);
|
|
}
|
|
|
|
int GFrame::ConGetTitle(char *Title, int MaxLen, char *STitle, int SMaxLen) {
|
|
return Peer->ConGetTitle(Title, MaxLen, STitle, SMaxLen);
|
|
}
|
|
|
|
int GFrame::ConSetSize(int X, int Y) {
|
|
return Peer->ConSetSize(X, Y);
|
|
}
|
|
|
|
int GFrame::ConQuerySize(int *X, int *Y) {
|
|
return Peer->ConQuerySize(X, Y);
|
|
}
|
|
|
|
int GFrame::ConSplitView(GView *view, GView *newview) {
|
|
int dmy;
|
|
|
|
newview->Parent = this;
|
|
newview->Peer->wX = 0;
|
|
ConQuerySize(&newview->Peer->wW, &dmy);
|
|
if (ShowVScroll)
|
|
newview->Peer->wW--;
|
|
newview->Peer->wY = view->Peer->wY + view->Peer->wH / 2;
|
|
newview->Peer->wH = view->Peer->wH - view->Peer->wH / 2;
|
|
if (ShowHScroll) {
|
|
newview->Peer->wY++;
|
|
newview->Peer->wH--;
|
|
}
|
|
view->Peer->wH /= 2;
|
|
view->ConSetSize(view->Peer->wW, view->Peer->wH);
|
|
newview->ConSetSize(newview->Peer->wW, newview->Peer->wH);
|
|
InsertView(view, newview);
|
|
return 0;
|
|
}
|
|
|
|
int GFrame::ConCloseView(GView * /*view*/) {
|
|
return 0;
|
|
}
|
|
|
|
int GFrame::ConResizeView(GView * /*view*/, int /*DeltaY*/) {
|
|
return 0;
|
|
}
|
|
|
|
int GFrame::AddView(GView *view) {
|
|
if (Active != 0) {
|
|
return ConSplitView(Active, view);
|
|
} else {
|
|
int W, H;
|
|
|
|
view->Parent = this;
|
|
view->Prev = view->Next = 0;
|
|
|
|
view->Peer->wX = 0;
|
|
if (ShowMenuBar)
|
|
view->Peer->wY = 1;
|
|
else
|
|
view->Peer->wY = 0;
|
|
ConQuerySize(&W, &H);
|
|
if (ShowMenuBar)
|
|
H--;
|
|
if (ShowVScroll)
|
|
W--;
|
|
if (ShowHScroll)
|
|
H--;
|
|
view->ConSetSize(W, H);
|
|
InsertView(Top, view);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void GFrame::Update() {
|
|
GView *v = Active;
|
|
|
|
UpdateMenu();
|
|
while (v) {
|
|
v->Update();
|
|
if ((ShowVScroll || ShowHScroll) && (v->Peer->sbVupdate || v->Peer->sbHupdate)) {
|
|
v->Peer->DrawScrollBar();
|
|
v->Peer->sbVupdate = 0;
|
|
v->Peer->sbHupdate = 0;
|
|
}
|
|
v = v->Next;
|
|
if (v == Active)
|
|
break;
|
|
}
|
|
}
|
|
|
|
void GFrame::UpdateMenu() {
|
|
if (ShowMenuBar)
|
|
DrawMenuBar();
|
|
}
|
|
|
|
void GFrame::Repaint() {
|
|
GView *v = Active;
|
|
|
|
if (ShowMenuBar)
|
|
DrawMenuBar();
|
|
while (v) {
|
|
v->Repaint();
|
|
if (ShowVScroll || ShowHScroll) {
|
|
v->Peer->DrawScrollBar();
|
|
v->Peer->sbVupdate = 0;
|
|
v->Peer->sbHupdate = 0;
|
|
}
|
|
v = v->Next;
|
|
if (v == Active)
|
|
break;
|
|
}
|
|
}
|
|
|
|
void GFrame::InsertView(GView *Prev, GView *view) {
|
|
if (!view) return ;
|
|
if (Prev) {
|
|
view->Prev = Prev;
|
|
view->Next = Prev->Next;
|
|
Prev->Next = view;
|
|
view->Next->Prev = view;
|
|
} else {
|
|
view->Prev = view->Next = view;
|
|
Top = view;
|
|
}
|
|
if (Active == 0) {
|
|
Active = view;
|
|
Active->Activate(1);
|
|
}
|
|
}
|
|
|
|
void GFrame::RemoveView(GView *view) {
|
|
if (!view) return ;
|
|
|
|
if (Active == view)
|
|
Active->Activate(0);
|
|
if (view->Next == view) {
|
|
Top = Active = 0;
|
|
delete this;
|
|
} else {
|
|
view->Next->Prev = view->Prev;
|
|
view->Prev->Next = view->Next;
|
|
|
|
if (Top == view) {
|
|
Top = view->Next;
|
|
Top->Peer->wY -= view->Peer->wH;
|
|
Top->ConSetSize(Top->Peer->wW, Top->Peer->wH + view->Peer->wH + (ShowHScroll ? 1 : 0));
|
|
} else {
|
|
view->Prev->ConSetSize(view->Prev->Peer->wW,
|
|
view->Prev->Peer->wH + view->Peer->wH + (ShowHScroll ? 1 : 0));
|
|
}
|
|
|
|
if (Active == view) {
|
|
Active = view->Prev;
|
|
Active->Activate(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GFrame::SelectNext(int back) {
|
|
GView *c = Active;
|
|
|
|
if (c == 0 && Top == 0)
|
|
return;
|
|
|
|
if (FocusCapture != 0)
|
|
return ;
|
|
|
|
else if (c == 0)
|
|
c = Active = Top;
|
|
else
|
|
if (back) {
|
|
Active = Active->Prev;
|
|
} else {
|
|
Active = Active->Next;
|
|
}
|
|
if (c != Active) {
|
|
if (c)
|
|
c->Activate(0);
|
|
if (Active)
|
|
Active->Activate(1);
|
|
}
|
|
}
|
|
|
|
int GFrame::SelectView(GView *view) {
|
|
if (Top == 0)
|
|
return 0;
|
|
|
|
if (FocusCapture != 0)
|
|
view = view;
|
|
|
|
if (Active)
|
|
Active->Activate(0);
|
|
Active = view;
|
|
if (Active)
|
|
Active->Activate(1);
|
|
return 1;
|
|
}
|
|
|
|
void GFrame::Resize(int width, int height) {
|
|
GView *V;
|
|
int count = 0;
|
|
|
|
|
|
V = Top;
|
|
while (V) {
|
|
count++;
|
|
if (V == Top) break;
|
|
}
|
|
if (height < 2 * count + 2 || width < 16) {
|
|
::ConSetSize(16, 2 * count + 1);
|
|
return;
|
|
}
|
|
|
|
if (!Top)
|
|
return;
|
|
|
|
if (ShowVScroll)
|
|
width--;
|
|
if (ShowHScroll)
|
|
height--;
|
|
|
|
// fprintf(stderr, "Resize: %d %d\n", width, height);
|
|
|
|
V = Top->Prev;
|
|
|
|
while (V != Top) {
|
|
int h, y;
|
|
|
|
h = V->Peer->wH;
|
|
y = V->Peer->wY;
|
|
|
|
if (y >= height - 2) {
|
|
y = height - 2;
|
|
}
|
|
if (y + h != height) {
|
|
h = height - y;
|
|
}
|
|
V->Peer->wY = y;
|
|
V->ConSetSize(width, h);
|
|
height = y;
|
|
V = V->Prev;
|
|
}
|
|
if (ShowMenuBar)
|
|
height--;
|
|
Top->ConSetSize(width, height);
|
|
Repaint();
|
|
// fprintf(stderr, "Resize: %d %d Done\n", width, height);
|
|
}
|
|
|
|
int GFrame::ExecMainMenu(char Sub) {
|
|
NextEvent.What = evCommand;
|
|
NextEvent.Msg.Command = cmMainMenu;
|
|
NextEvent.Msg.Param1 = Sub;
|
|
return 0;
|
|
}
|
|
|
|
int GFrame::SetMenu(const char *Name) {
|
|
if (Menu) free(Menu);
|
|
Menu = strdup(Name);
|
|
return 0;
|
|
}
|
|
|
|
void GFrame::Show() {
|
|
}
|
|
|
|
void GFrame::Activate() {
|
|
frames = this;
|
|
}
|
|
|
|
int GUI::ConGrabEvents(TEventMask /*EventMask*/) {
|
|
return 0;
|
|
}
|
|
|
|
void GUI::DispatchEvent(GFrame * /*frame*/, GView *view, TEvent &Event) {
|
|
if (Event.What != evNone) {
|
|
if (view)
|
|
view->HandleEvent(Event);
|
|
}
|
|
}
|
|
|
|
int GUI::ConGetEvent(TEventMask EventMask, TEvent *Event, int WaitTime, int Delete, GView **view) {
|
|
if (view)
|
|
*view = 0;
|
|
return ::ConGetEvent(EventMask, Event, WaitTime, Delete);
|
|
}
|
|
|
|
int GUI::ConPutEvent(TEvent Event) {
|
|
return ::ConPutEvent(Event);
|
|
}
|
|
|
|
int GUI::ConFlush(void) {
|
|
return 0;
|
|
}
|
|
|
|
static inline int scrollBreak(TEvent &E)
|
|
{
|
|
#if defined(DOS) || defined(DOSP32)
|
|
// workaround until mouse code in con_dosx.cpp is finished
|
|
return (E.What != evMouseDown);
|
|
#else
|
|
return (E.What == evMouseUp);
|
|
#endif
|
|
}
|
|
|
|
void HandleVScroll(GView *view, TEvent &E) {
|
|
int y; //, x
|
|
int wY, wH;
|
|
TEvent E1;
|
|
|
|
//x = E.Mouse.X;
|
|
y = E.Mouse.Y;
|
|
wY = view->Peer->wY;
|
|
wH = view->Peer->wH;
|
|
if (y == wY) {
|
|
do {
|
|
E1.What = evCommand;
|
|
E1.Msg.View = view;
|
|
E1.Msg.Command = cmVScrollUp;
|
|
gui->DispatchEvent(frames, view, E1);
|
|
frames->Update();
|
|
do {
|
|
ConGetEvent(evMouse | evNotify, &E, -1, 1);
|
|
if (E.What & evNotify)
|
|
gui->DispatchEvent(frames, view, E);
|
|
} while (E.What & evNotify);
|
|
if (scrollBreak(E)) break;
|
|
} while (1);
|
|
} else if (y == wY + wH - 1) {
|
|
do {
|
|
E1.What = evCommand;
|
|
E1.Msg.View = view;
|
|
E1.Msg.Command = cmVScrollDown;
|
|
gui->DispatchEvent(frames, view, E1);
|
|
frames->Update();
|
|
do {
|
|
ConGetEvent(evMouse | evNotify, &E, -1, 1);
|
|
if (E.What & evNotify)
|
|
gui->DispatchEvent(frames, view, E);
|
|
} while (E.What & evNotify);
|
|
if (scrollBreak(E)) break;
|
|
} while (1);
|
|
} else if (y < wY + view->Peer->SbVBegin + 1) {
|
|
do {
|
|
E1.What = evCommand;
|
|
E1.Msg.View = view;
|
|
E1.Msg.Command = cmVScrollPgUp;
|
|
gui->DispatchEvent(frames, view, E1);
|
|
frames->Update();
|
|
do {
|
|
ConGetEvent(evMouse | evNotify, &E, -1, 1);
|
|
if (E.What & evNotify)
|
|
gui->DispatchEvent(frames, view, E);
|
|
} while (E.What & evNotify);
|
|
if (scrollBreak(E)) break;
|
|
} while (1);
|
|
} else if (y > wY + view->Peer->SbVEnd + 1) {
|
|
do {
|
|
E1.What = evCommand;
|
|
E1.Msg.View = view;
|
|
E1.Msg.Command = cmVScrollPgDn;
|
|
gui->DispatchEvent(frames, view, E1);
|
|
frames->Update();
|
|
do {
|
|
ConGetEvent(evMouse | evNotify, &E, -1, 1);
|
|
if (E.What & evNotify)
|
|
gui->DispatchEvent(frames, view, E);
|
|
} while (E.What & evNotify);
|
|
if (scrollBreak(E)) break;
|
|
} while (1);
|
|
} else {
|
|
int delta = y - 1 - view->Peer->SbVBegin - wY;
|
|
|
|
do {
|
|
E1.What = evCommand;
|
|
E1.Msg.View = view;
|
|
E1.Msg.Command = cmVScrollMove;
|
|
E1.Msg.Param1 = (E.Mouse.Y - wY - 1 - delta + 1) * view->Peer->sbVtotal / (wH - 2);
|
|
// printf("YPos = %d %d %d \n\x7", E.Mouse.Y, wY, delta);
|
|
gui->DispatchEvent(frames, view, E1);
|
|
frames->Update();
|
|
do {
|
|
ConGetEvent(evMouse | evNotify, &E, -1, 1);
|
|
if (E.What & evNotify)
|
|
gui->DispatchEvent(frames, view, E);
|
|
} while (E.What & evNotify);
|
|
if (scrollBreak(E)) break;
|
|
} while (1);
|
|
}
|
|
E.What = evNone;
|
|
}
|
|
|
|
void HandleHScroll(GView *view, TEvent &E) {
|
|
int x; //, x
|
|
int wX, wW;
|
|
TEvent E1;
|
|
|
|
//x = E.Mouse.X;
|
|
x = E.Mouse.X;
|
|
wX = view->Peer->wX;
|
|
wW = view->Peer->wW;
|
|
if (x == wX) {
|
|
do {
|
|
E1.What = evCommand;
|
|
E1.Msg.View = view;
|
|
E1.Msg.Command = cmHScrollLeft;
|
|
gui->DispatchEvent(frames, view, E1);
|
|
frames->Update();
|
|
do {
|
|
ConGetEvent(evMouse | evNotify, &E, -1, 1);
|
|
if (E.What & evNotify)
|
|
gui->DispatchEvent(frames, view, E);
|
|
} while (E.What & evNotify);
|
|
if (scrollBreak(E)) break;
|
|
} while (1);
|
|
} else if (x == wX + wW - 1) {
|
|
do {
|
|
E1.What = evCommand;
|
|
E1.Msg.View = view;
|
|
E1.Msg.Command = cmHScrollRight;
|
|
gui->DispatchEvent(frames, view, E1);
|
|
frames->Update();
|
|
do {
|
|
ConGetEvent(evMouse | evNotify, &E, -1, 1);
|
|
if (E.What & evNotify)
|
|
gui->DispatchEvent(frames, view, E);
|
|
} while (E.What & evNotify);
|
|
if (scrollBreak(E)) break;
|
|
} while (1);
|
|
} else if (x < wX + view->Peer->SbHBegin + 1) {
|
|
do {
|
|
E1.What = evCommand;
|
|
E1.Msg.View = view;
|
|
E1.Msg.Command = cmHScrollPgLt;
|
|
gui->DispatchEvent(frames, view, E1);
|
|
frames->Update();
|
|
do {
|
|
ConGetEvent(evMouse | evNotify, &E, -1, 1);
|
|
if (E.What & evNotify)
|
|
gui->DispatchEvent(frames, view, E);
|
|
} while (E.What & evNotify);
|
|
if (scrollBreak(E)) break;
|
|
} while (1);
|
|
} else if (x > wX + view->Peer->SbHEnd + 1) {
|
|
do {
|
|
E1.What = evCommand;
|
|
E1.Msg.View = view;
|
|
E1.Msg.Command = cmHScrollPgRt;
|
|
gui->DispatchEvent(frames, view, E1);
|
|
frames->Update();
|
|
do {
|
|
ConGetEvent(evMouse | evNotify, &E, -1, 1);
|
|
if (E.What & evNotify)
|
|
gui->DispatchEvent(frames, view, E);
|
|
} while (E.What & evNotify);
|
|
if (scrollBreak(E)) break;
|
|
} while (1);
|
|
} else {
|
|
int delta = x - 1 - view->Peer->SbHBegin - wX;
|
|
|
|
do {
|
|
E1.What = evCommand;
|
|
E1.Msg.View = view;
|
|
E1.Msg.Command = cmHScrollMove;
|
|
E1.Msg.Param1 = (E.Mouse.X - wX - 1 - delta + 1) * view->Peer->sbHtotal / (wW - 2);
|
|
// printf("YPos = %d %d %d \n\x7", E.Mouse.Y, wY, delta);
|
|
gui->DispatchEvent(frames, view, E1);
|
|
frames->Update();
|
|
do {
|
|
ConGetEvent(evMouse | evNotify, &E, -1, 1);
|
|
if (E.What & evNotify)
|
|
gui->DispatchEvent(frames, view, E);
|
|
} while (E.What & evNotify);
|
|
if (scrollBreak(E)) break;
|
|
} while (1);
|
|
}
|
|
E.What = evNone;
|
|
}
|
|
|
|
void GUI::ProcessEvent() {
|
|
TEvent E;
|
|
|
|
E = NextEvent;
|
|
if (E.What != evNone) {
|
|
NextEvent.What = evNone;
|
|
}
|
|
if (E.What == evNone &&
|
|
( ConGetEvent(evMouse | evCommand | evKeyboard, &E, 0, 1, 0) == -1 ||
|
|
E.What == evNone )
|
|
)
|
|
{
|
|
frames->Update();
|
|
while(ConGetEvent(evMouse | evCommand | evKeyboard, &E, -1, 1, 0) == -1 ||
|
|
(E.What == evMouseMove && E.Mouse.Buttons == 0));
|
|
}
|
|
if (E.What != evNone) {
|
|
GView *view = frames->Active;
|
|
|
|
if (E.What & evMouse) {
|
|
if (E.What == evMouseDown && E.Mouse.Y == 0 && ShowMenuBar &&
|
|
MouseCapture == 0 && FocusCapture == 0)
|
|
{
|
|
frames->Update(); // sync before menu
|
|
if (ExecMainMenu(E, 0) == -1) {
|
|
if (E.What == evCommand && E.Msg.Command == cmResize) {
|
|
int X, Y;
|
|
|
|
ConQuerySize(&X, &Y);
|
|
frames->Resize(X, Y);
|
|
}
|
|
E.What = evNone;
|
|
}
|
|
// fprintf(stderr, "Command got = %d\n", E.Msg.Command);
|
|
}
|
|
if (E.What == evMouseDown && MouseCapture == 0 && FocusCapture == 0) {
|
|
GView *V = frames->Active;
|
|
|
|
while (V) {
|
|
if (E.Mouse.Y >= V->Peer->wY &&
|
|
E.Mouse.Y < V->Peer->wY + V->Peer->wH + (ShowHScroll ? 1 : 0))
|
|
{
|
|
frames->SelectView(V);
|
|
view = V;
|
|
break;
|
|
}
|
|
V = V->Next;
|
|
if (V == frames->Active)
|
|
break;
|
|
}
|
|
}
|
|
if (ShowVScroll && ShowHScroll && E.What == evMouseDown &&
|
|
MouseCapture == 0 && FocusCapture == 0 &&
|
|
E.Mouse.Y == view->Peer->wY + view->Peer->wH &&
|
|
E.Mouse.X == view->Peer->wX + view->Peer->wW)
|
|
{
|
|
} else {
|
|
if (ShowVScroll && E.What == evMouseDown && MouseCapture == 0 && FocusCapture == 0 &&
|
|
E.Mouse.X == view->Peer->wX + view->Peer->wW)
|
|
{
|
|
HandleVScroll(view, E);
|
|
return ;
|
|
}
|
|
if (ShowHScroll && E.What == evMouseDown && MouseCapture == 0 && FocusCapture == 0 &&
|
|
E.Mouse.Y == view->Peer->wY + view->Peer->wH)
|
|
{
|
|
HandleHScroll(view, E);
|
|
return ;
|
|
}
|
|
}
|
|
if (E.What & evMouse) {
|
|
E.Mouse.Y -= view->Peer->wY;
|
|
E.Mouse.X -= view->Peer->wX;
|
|
}
|
|
}
|
|
if (E.What == evCommand) {
|
|
switch (E.Msg.Command) {
|
|
case cmResize:
|
|
{
|
|
int X, Y;
|
|
|
|
ConQuerySize(&X, &Y);
|
|
frames->Resize(X, Y);
|
|
}
|
|
break;
|
|
case cmMainMenu:
|
|
{
|
|
char Sub = (char)E.Msg.Param1;
|
|
|
|
frames->Update(); // sync before menu
|
|
if (::ExecMainMenu(E, Sub) != 1) {;
|
|
if (E.What == evCommand && E.Msg.Command == cmResize) {
|
|
int X, Y;
|
|
|
|
ConQuerySize(&X, &Y);
|
|
frames->Resize(X, Y);
|
|
}
|
|
E.What = evNone;
|
|
}
|
|
}
|
|
break;
|
|
case cmPopupMenu:
|
|
{
|
|
int id = E.Msg.Param1;
|
|
int Cols, Rows;
|
|
|
|
if (id == -1) return;
|
|
frames->ConQuerySize(&Cols, &Rows);
|
|
int x = Cols / 2, y = Rows / 2;
|
|
::ConQueryMousePos(&x, &y);
|
|
|
|
frames->Update(); // sync before menu
|
|
if (::ExecVertMenu(x, y, id, E, 0) != 1) {
|
|
if (E.What == evCommand && E.Msg.Command == cmResize) {
|
|
int X, Y;
|
|
|
|
ConQuerySize(&X, &Y);
|
|
frames->Resize(X, Y);
|
|
}
|
|
E.What = evNone;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (E.What != evNone)
|
|
DispatchEvent(frames, view, E);
|
|
}
|
|
}
|
|
|
|
int GUI::Run() {
|
|
if (Start(fArgc, fArgv) == 0) {
|
|
doLoop = 1;
|
|
while (doLoop)
|
|
ProcessEvent();
|
|
Stop();
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int GUI::multiFrame() {
|
|
return 0;
|
|
}
|
|
|
|
void DieError(int rc, const char *msg, ...) {
|
|
va_list ap;
|
|
|
|
va_start(ap, msg);
|
|
vfprintf(stderr, msg, ap);
|
|
va_end(ap);
|
|
fprintf(stderr, "\n");
|
|
exit(rc);
|
|
}
|