home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ftes46b5.zip / ftes46b5 / src / g_text.cpp < prev    next >
C/C++ Source or Header  |  1997-08-25  |  31KB  |  1,229 lines

  1. /*    g_text.cpp
  2.  *
  3.  *    Copyright (c) 1994-1996, Marko Macek
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <assert.h>
  14. #include <signal.h>
  15. #include <stdarg.h>
  16.  
  17. #include "console.h"
  18. #include "gui.h"
  19. #include "c_mode.h"
  20. #include "c_color.h"
  21.  
  22. int ShowVScroll = 1;
  23. int ShowHScroll = 1;
  24. int ShowMenuBar = 1;
  25. int ShowToolBar = 0;
  26. unsigned long HaveGUIDialogs = 0; // no gui dialogs in text gui
  27.  
  28. GFrame *frames = 0;
  29. GUI *gui = 0;
  30.  
  31. GView *MouseCapture = 0;
  32. GView *FocusCapture = 0;
  33.  
  34. TEvent NextEvent = { 0 };
  35.  
  36. #define sfFocus   1
  37.  
  38. class UpMenu;
  39.  
  40. extern int ExecMainMenu(TEvent &E, char sub);
  41. extern int ExecVertMenu(int x, int y, int id, TEvent &E, UpMenu *up);
  42.  
  43. class GViewPeer {
  44. public:
  45.     GView *View;
  46.     int wX, wY, wW, wH, wState;
  47.     int cX, cY, cVisible, cStart, cEnd;
  48.     int sbVstart, sbVamount, sbVtotal, sbVupdate;
  49.     int sbHstart, sbHamount, sbHtotal, sbHupdate;
  50.     int SbVBegin, SbVEnd, SbHBegin, SbHEnd;
  51.     
  52.     GViewPeer(GView *view, int XSize, int YSize);
  53.     ~GViewPeer();
  54.  
  55.     int ConPutBox(int X, int Y, int W, int H, PCell Cell);
  56.     int ConGetBox(int X, int Y, int W, int H, PCell Cell);
  57.     int ConPutLine(int X, int Y, int W, int H, PCell Cell);
  58.     int ConSetBox(int X, int Y, int W, int H, TCell Cell);
  59.     int ConScroll(int Way, int X, int Y, int W, int H, TAttr Fill, int Count);
  60.  
  61.     int ConSetSize(int X, int Y);
  62.     int ConQuerySize(int *X, int *Y);
  63.     
  64.     int ConSetCursorPos(int X, int Y);
  65.     int ConQueryCursorPos(int *X, int *Y);
  66.     int ConShowCursor();
  67.     int ConHideCursor();
  68.     int ConCursorVisible();
  69.     int ConSetCursorSize(int Start, int End);
  70.     
  71.     int CaptureMouse(int grab);
  72.     int CaptureFocus(int grab);
  73.     
  74.     int QuerySbVPos();
  75.     int SetSbVPos(int Start, int Amount, int Total);
  76.     int SetSbHPos(int Start, int Amount, int Total);
  77.     int ExpandHeight(int DeltaY);
  78.  
  79.     int DrawScrollBar();
  80.     int UpdateCursor();
  81. };      
  82.  
  83. class GFramePeer {
  84. public:
  85.     int fW, fH;
  86.     GFrame *Frame;
  87.     
  88.     GFramePeer(GFrame *aFrame, int Width, int Height);
  89.     ~GFramePeer();
  90.     
  91.     int ConSetTitle(char *Title, char *STitle);
  92.     int ConGetTitle(char *Title, int MaxLen, char *STitle, int SMaxLen);
  93.     
  94.     int ConSetSize(int X, int Y);
  95.     int ConQuerySize(int *X, int *Y);
  96.  
  97. };
  98.  
  99. ///////////////////////////////////////////////////////////////////////////
  100.  
  101. GViewPeer::GViewPeer(GView *view, int XSize, int YSize) {
  102.     View = view;
  103.     wX = 0;
  104.     wY = 0;
  105.     wW = XSize;
  106.     wH = YSize;
  107.     sbVtotal = 0;
  108.     sbVstart = 0;
  109.     sbVamount = 0;
  110.     sbVupdate = 1;
  111.     sbHtotal = 0;
  112.     sbHstart = 0;
  113.     sbHamount = 0;
  114.     sbHupdate = 1;
  115.     wState = 0;
  116.     cVisible = 1;
  117.     cStart = 0; // %
  118.     cEnd = 100;
  119.     cX = cY = 0;
  120. }
  121.  
  122. GViewPeer::~GViewPeer() {
  123.     if (MouseCapture == View)
  124.         MouseCapture = 0;
  125.     if (FocusCapture == View)
  126.         FocusCapture = 0;
  127. }
  128.  
  129. int GViewPeer::ConPutBox(int X, int Y, int W, int H, PCell Cell) {
  130.     return ::ConPutBox(X + wX, Y + wY, W, H, Cell);
  131. }
  132.  
  133. int GViewPeer::ConGetBox(int X, int Y, int W, int H, PCell Cell) {
  134.     return ::ConGetBox(X + wX, Y + wY, W, H, Cell);
  135. }
  136.  
  137. int GViewPeer::ConPutLine(int X, int Y, int W, int H, PCell Cell) {
  138.     return ::ConPutLine(X + wX, Y + wY, W, H, Cell);
  139. }
  140.  
  141. int GViewPeer::ConSetBox(int X, int Y, int W, int H, TCell Cell) {
  142.     return ::ConSetBox(X + wX, Y + wY, W, H, Cell);
  143. }
  144.  
  145. int GViewPeer::ConScroll(int Way, int X, int Y, int W, int H, TAttr Fill, int Count) {
  146.     return ::ConScroll(Way, X + wX, Y + wY, W, H, Fill, Count);
  147. }
  148.     
  149. int GViewPeer::ConSetSize(int X, int Y) {
  150.     wW = X;
  151.     wH = Y;
  152.     return 1;
  153. }
  154.  
  155. int GViewPeer::ConQuerySize(int *X, int *Y) {
  156.     if (X) *X = wW;
  157.     if (Y) *Y = wH;
  158.     return 1;
  159. }
  160.  
  161. int GViewPeer::ConSetCursorPos(int X, int Y) {
  162.     if (X < 0) X = 0;
  163.     if (X >= wW) X = wW - 1;
  164.     if (Y < 0) Y = 0;
  165.     if (Y >= wH) Y = wH - 1;
  166.     cX = X;
  167.     cY = Y;
  168.     if (wState & sfFocus)
  169.         return ::ConSetCursorPos(cX + wX, cY + wY);
  170.     else
  171.         return 1;
  172. }
  173.  
  174. int GViewPeer::ConQueryCursorPos(int *X, int *Y) {
  175.     if (X) *X = cX;
  176.     if (Y) *Y = cY;
  177.     return 1;
  178. }
  179.  
  180. int GViewPeer::ConShowCursor() {
  181.     cVisible = 1;
  182.     if (wState & sfFocus)
  183.         return ::ConShowCursor();
  184.     else
  185.         return 1;
  186. }
  187.  
  188. int GViewPeer::ConHideCursor() {
  189.     cVisible = 0;
  190.     if (wState & sfFocus)
  191.         return ::ConHideCursor();
  192.     else
  193.         return 1;
  194. }
  195.  
  196. int GViewPeer::ConCursorVisible() {
  197.     return cVisible;
  198. }
  199.  
  200. int GViewPeer::ConSetCursorSize(int Start, int End) {
  201.     cStart = Start;
  202.     cEnd = End;
  203.     if (wState & sfFocus)
  204.         return ::ConSetCursorSize(Start, End);
  205.     else
  206.         return 1;
  207. }
  208.  
  209. int GViewPeer::CaptureMouse(int grab) {
  210.     if (MouseCapture == 0) {
  211.         if (grab)
  212.             MouseCapture = View;
  213.         else
  214.             return 0;
  215.     } else {
  216.         if (grab || MouseCapture != View)
  217.             return 0;
  218.         else
  219.             MouseCapture = 0;
  220.     }
  221.     return 1;
  222. }
  223.  
  224. int GViewPeer::CaptureFocus(int grab) {
  225.     if (FocusCapture == 0) {
  226.         if (grab)
  227.             FocusCapture = View;
  228.         else
  229.             return 0;
  230.     } else {
  231.         if (grab || FocusCapture != View)
  232.             return 0;
  233.         else
  234.             FocusCapture = 0;
  235.     }
  236.     return 1;
  237. }
  238.  
  239. int GViewPeer::ExpandHeight(int DeltaY) {
  240.     if (View->Parent->Top == View->Next)
  241.         return -1;
  242.     if (DeltaY + wH < 3)
  243.         DeltaY = - (wH - 3);
  244.     if (View->Next->Peer->wH - DeltaY < 3)
  245.         DeltaY = View->Next->Peer->wH - 3;
  246.     View->Peer->ConSetSize(wW, wH + DeltaY);
  247.     View->Next->Peer->wY += DeltaY;
  248.     View->Next->Peer->ConSetSize(View->Next->Peer->wW, View->Next->Peer->wH - DeltaY);
  249.     View->Resize(View->Peer->wW, View->Peer->wH);
  250.     View->Next->Resize(View->Next->Peer->wW, View->Next->Peer->wH);
  251.     return 0;
  252. }
  253.  
  254. int GViewPeer::QuerySbVPos() {
  255.     return sbVstart;
  256. }
  257.  
  258. int GViewPeer::SetSbVPos(int Start, int Amount, int Total) {
  259.     if (sbVstart != Start ||
  260.         sbVamount != Amount ||
  261.         sbVtotal != Total)
  262.     {
  263.         sbVstart = Start;
  264.         sbVamount = Amount;
  265.         sbVtotal = Total;
  266.         sbVupdate = 1;
  267. //        DrawScrollBar();
  268.     }
  269.     return 1;
  270. }
  271.  
  272. int GViewPeer::SetSbHPos(int Start, int Amount, int Total) {
  273.     if (sbHstart != Start ||
  274.         sbHamount != Amount ||
  275.         sbHtotal != Total)
  276.     {
  277.         sbHstart = Start;
  278.         sbHamount = Amount;
  279.         sbHtotal = Total;
  280.         sbHupdate = 1;
  281. //        DrawScrollBar();
  282.     }
  283.     return 1;
  284. }
  285.  
  286. int GViewPeer::UpdateCursor() {
  287.     ConSetCursorPos(cX, cY);
  288.     ConSetCursorSize(cStart, cEnd);
  289.     if (cVisible)
  290.         ConShowCursor();
  291.     else
  292.         ConHideCursor();
  293.     return 0;
  294. }
  295.  
  296. int GViewPeer::DrawScrollBar() {
  297.     TDrawBuffer B;
  298.     int NRows, NCols, I;
  299.     int W, H;
  300.     char fore = ConGetDrawChar(DCH_HFORE);
  301.     char back = ConGetDrawChar(DCH_HBACK);
  302.     
  303.     ConQuerySize(&W, &H);
  304.  
  305.     if (ShowVScroll) {
  306.         MoveCh(B, ConGetDrawChar(DCH_AUP), hcScrollBar_Arrows, 1);
  307.         ConPutBox(W, 0, 1, 1, B);
  308.         MoveCh(B, ConGetDrawChar(DCH_ADOWN), hcScrollBar_Arrows, 1);
  309.         ConPutBox(W, H - 1, 1, 1, B);
  310.         
  311.         NRows = H - 2;
  312.         
  313.         if (sbVtotal <= NRows) {
  314.             SbVBegin = 0;
  315.             SbVEnd = NRows - 1;
  316.         } else {
  317.             SbVBegin = NRows * sbVstart / sbVtotal;
  318.             SbVEnd   = SbVBegin + NRows * sbVamount / sbVtotal;
  319.         }
  320.         
  321.         for (I = 0; I < NRows; I++) {
  322.             if (I >= SbVBegin && I <= SbVEnd)
  323.                 MoveCh(B, fore, hcScrollBar_Fore, 1);
  324.             else
  325.                 MoveCh(B, back, hcScrollBar_Back, 1);
  326.             ConPutBox(W, I + 1, 1, 1, B);
  327.         }
  328.     }
  329.     if (ShowHScroll) {
  330.         MoveCh(B, ConGetDrawChar(DCH_ALEFT), hcScrollBar_Arrows, 1);
  331.         ConPutBox(0, H, 1, 1, B);
  332.         MoveCh(B, ConGetDrawChar(DCH_ARIGHT), hcScrollBar_Arrows, 1);
  333.         ConPutBox(W - 1, H, 1, 1, B);
  334.         
  335.         NCols = W - 2;
  336.         
  337.         if (sbHtotal <= NCols) {
  338.             SbHBegin = 0;
  339.             SbHEnd = NCols - 1;
  340.         } else {
  341.             SbHBegin = NCols * sbHstart / sbHtotal;
  342.             SbHEnd   = SbHBegin + NCols * sbHamount / sbHtotal;
  343.         }
  344.  
  345.         // could be made faster
  346.         for (I = 0; I < NCols; I++) {
  347.             if (I >= SbHBegin && I <= SbHEnd)
  348.                 MoveCh(B, fore, hcScrollBar_Fore, 1);
  349.             else
  350.                 MoveCh(B, back, hcScrollBar_Back, 1);
  351.             ConPutBox(I + 1, H, 1, 1, B);
  352.         }
  353.     }
  354.     if (ShowVScroll && ShowHScroll) {
  355.         MoveCh(B, ' ', hcScrollBar_Arrows, 1);
  356.         ConPutBox(W, H, 1, 1, B);
  357.     }
  358.         
  359.     return 0;
  360. }
  361.  
  362.  
  363. ///////////////////////////////////////////////////////////////////////////
  364.  
  365. GView::GView(GFrame *parent, int XSize, int YSize) {
  366.     Parent = parent;
  367.     Prev = Next = 0;
  368.     Peer = new GViewPeer(this, XSize, YSize);
  369.     if (Parent)
  370.         Parent->AddView(this);
  371. }
  372.  
  373. GView::~GView() {
  374.     if (Parent)
  375.         Parent->RemoveView(this);
  376.     delete Peer;
  377. }
  378.  
  379. int GView::ConClear() {
  380.     int W, H;
  381.     TDrawBuffer B;
  382.     
  383.     ConQuerySize(&W, &H);
  384.     MoveChar(B, 0, W, ' ', 0x07, 1);
  385.     ConSetBox(0, 0, W, H, B[0]);
  386.     return 1;
  387. }
  388.  
  389. int GView::ConPutBox(int X, int Y, int W, int H, PCell Cell) {
  390.     return Peer->ConPutBox(X, Y, W, H, Cell);
  391. }
  392.  
  393. int GView::ConGetBox(int X, int Y, int W, int H, PCell Cell) {
  394.     return Peer->ConGetBox(X, Y, W, H, Cell);
  395. }
  396.  
  397. int GView::ConPutLine(int X, int Y, int W, int H, PCell Cell) {
  398.     return Peer->ConPutLine(X, Y, W, H, Cell);
  399. }
  400.  
  401. int GView::ConSetBox(int X, int Y, int W, int H, TCell Cell) {
  402.     return Peer->ConSetBox(X, Y, W, H, Cell);
  403. }
  404.  
  405. int GView::ConScroll(int Way, int X, int Y, int W, int H, TAttr Fill, int Count) {
  406.     return Peer->ConScroll(Way, X, Y, W, H, Fill, Count);
  407. }
  408.  
  409. int GView::ConSetSize(int X, int Y) {
  410.     if (Peer->ConSetSize(X, Y))
  411.         Resize(X, Y);
  412.     else
  413.         return 0;
  414.     return 1;
  415. }
  416.  
  417. int GView::ConQuerySize(int *X, int *Y) {
  418.     return Peer->ConQuerySize(X, Y);
  419. }
  420.  
  421. int GView::ConSetCursorPos(int X, int Y) {
  422.     return Peer->ConSetCursorPos(X, Y);
  423. }
  424.  
  425. int GView::ConQueryCursorPos(int *X, int *Y) {
  426.     return Peer->ConQueryCursorPos(X, Y);
  427. }
  428.  
  429. int GView::ConShowCursor() {
  430.     return Peer->ConShowCursor();
  431. }
  432.  
  433. int GView::ConHideCursor() {
  434.     return Peer->ConHideCursor();
  435. }
  436.  
  437. int GView::ConCursorVisible() {
  438.     return Peer->ConCursorVisible(); 
  439. }
  440.  
  441. int GView::ConSetCursorSize(int Start, int End) {
  442.     return Peer->ConSetCursorSize(Start, End);
  443. }
  444.  
  445. int GView::CaptureMouse(int grab) {
  446.     return Peer->CaptureMouse(grab);
  447. }
  448.  
  449. int GView::CaptureFocus(int grab) {
  450.     return Peer->CaptureFocus(grab);
  451. }
  452.  
  453. int GView::QuerySbVPos() {
  454.     return Peer->QuerySbVPos();
  455. }
  456.  
  457. int GView::SetSbVPos(int Start, int Amount, int Total) {
  458.     return Peer->SetSbVPos(Start, Amount, Total);
  459. }
  460.  
  461. int GView::SetSbHPos(int Start, int Amount, int Total) {
  462.     return Peer->SetSbHPos(Start, Amount, Total);
  463. }
  464.  
  465. int GView::ExpandHeight(int DeltaY) {
  466.     return Peer->ExpandHeight(DeltaY);
  467. }
  468.  
  469. void GView::Update() {
  470. }
  471.  
  472. void GView::Repaint() {
  473. }
  474.  
  475. void GView::HandleEvent(TEvent &/*Event*/) {
  476. }
  477.  
  478. void GView::Resize(int /*width*/, int /*height*/) {
  479.     Repaint();
  480. }
  481.  
  482. void GView::EndExec(int NewResult) {
  483.     Result = NewResult;
  484. }
  485.  
  486. int GView::Execute() {
  487.     int SaveRc = Result;
  488.     int NewResult;
  489.     int didFocus = 0;
  490.     
  491.     if (FocusCapture == 0) {
  492.         if (CaptureFocus(1) == 0) return -1;
  493.         didFocus = 1;
  494.     } else
  495.         if (FocusCapture != this)
  496.             return -1;
  497.     Result = -2;
  498.     while (Result == -2 && frames != 0)
  499.         gui->ProcessEvent();
  500.     NewResult = Result;
  501.     Result = SaveRc;
  502.     if (didFocus)
  503.         CaptureFocus(0);
  504.     return NewResult;
  505. }
  506.  
  507. int GView::IsActive() {
  508.     return (Parent->Active == this);
  509. }
  510.  
  511. void GView::Activate(int gotfocus) {
  512.     if (gotfocus) {
  513.         Peer->wState |= sfFocus;
  514.         Peer->UpdateCursor();
  515.     } else {
  516.         Peer->wState &= ~sfFocus;
  517.     }
  518.     Repaint();
  519. }
  520.  
  521. ///////////////////////////////////////////////////////////////////////////
  522.  
  523. GFramePeer::GFramePeer(GFrame *aFrame, int Width, int Height) {
  524.     Frame = aFrame;
  525.     if (Width != -1 && Height != -1)
  526.         ConSetSize(Width, Height);
  527.     ConQuerySize(&fW, &fH);
  528. }
  529.  
  530. GFramePeer::~GFramePeer() {
  531. }
  532.  
  533. int GFramePeer::ConSetSize(int X, int Y) {
  534.     return ::ConSetSize(X, Y);
  535. }
  536.  
  537. int GFramePeer::ConQuerySize(int *X, int *Y) {
  538.     ::ConQuerySize(&fW, &fH);
  539.     if (X) *X = fW;
  540.     if (Y) *Y = fH;
  541.     return 1;
  542. }   
  543.  
  544. //int GFrame::ConQuerySize(int *X, int *Y) {
  545. //    ::ConQuerySize(X, Y);
  546. //    if (ShowVScroll)
  547. //        --*X;
  548. //}
  549.  
  550. int GFramePeer::ConSetTitle(char *Title, char *STitle) {
  551.     ::ConSetTitle(Title, STitle);
  552.     return 0;
  553. }
  554.  
  555. int GFramePeer::ConGetTitle(char *Title, int MaxLen, char *STitle, int SMaxLen) {
  556.     return ::ConGetTitle(Title, MaxLen, STitle, SMaxLen);
  557. }
  558.  
  559. ///////////////////////////////////////////////////////////////////////////
  560.  
  561. GFrame::GFrame(int XSize, int YSize) {
  562.     Menu = 0;
  563.     if (frames == 0) {
  564.         frames = Prev = Next = this;
  565.     } else {
  566.         Next = frames->Next;
  567.         Prev = frames;
  568.         frames->Next->Prev = this;
  569.         frames->Next = this;
  570.         frames = this;
  571.     }
  572.     Top = Active = 0;
  573.     Peer = new GFramePeer(this, XSize, YSize);
  574. }
  575.  
  576. GFrame::~GFrame() {
  577.     if (Peer) {
  578.         delete Peer;
  579.         Peer = 0;
  580.     }
  581.     if (Next == this) {
  582.         frames = 0;
  583. //        printf("No more frames\x7\x7\n");
  584.     } else {
  585.         Next->Prev = Prev;
  586.         Prev->Next = Next;
  587.         frames = Next;
  588.     }
  589.     Next = Prev = 0;
  590.     free(Menu);
  591. }
  592.  
  593. int GFrame::ConSetTitle(char *Title, char *STitle) {
  594.     return Peer->ConSetTitle(Title, STitle);
  595. }
  596.  
  597. int GFrame::ConGetTitle(char *Title, int MaxLen, char *STitle, int SMaxLen) {
  598.     return Peer->ConGetTitle(Title, MaxLen, STitle, SMaxLen);
  599. }
  600.  
  601. int GFrame::ConSetSize(int X, int Y) {
  602.     return Peer->ConSetSize(X, Y);
  603. }
  604.  
  605. int GFrame::ConQuerySize(int *X, int *Y) {
  606.     return Peer->ConQuerySize(X, Y);
  607. }
  608.  
  609. int GFrame::ConSplitView(GView *view, GView *newview) {
  610.     int dmy;
  611.     
  612.     newview->Parent = this;
  613.     newview->Peer->wX = 0;
  614.     ConQuerySize(&newview->Peer->wW, &dmy);
  615.     if (ShowVScroll) 
  616.         newview->Peer->wW--;
  617.     newview->Peer->wY = view->Peer->wY + view->Peer->wH / 2;
  618.     newview->Peer->wH = view->Peer->wH - view->Peer->wH / 2;
  619.     if (ShowHScroll) {
  620.         newview->Peer->wY++;
  621.         newview->Peer->wH--;
  622.     }
  623.     view->Peer->wH /= 2;
  624.     view->ConSetSize(view->Peer->wW, view->Peer->wH);
  625.     newview->ConSetSize(newview->Peer->wW, newview->Peer->wH);
  626.     InsertView(view, newview);
  627.     return 0;
  628. }
  629.  
  630. int GFrame::ConCloseView(GView */*view*/) {
  631.     return 0;
  632. }
  633.  
  634. int GFrame::ConResizeView(GView */*view*/, int /*DeltaY*/) {
  635.     return 0;
  636. }
  637.  
  638. int GFrame::AddView(GView *view) {
  639.     if (Active != 0) {
  640.         return ConSplitView(Active, view);
  641.     } else {
  642.         int W, H;
  643.         
  644.         view->Parent = this;
  645.         view->Prev = view->Next = 0;
  646.         
  647.         view->Peer->wX = 0;
  648.         if (ShowMenuBar)
  649.             view->Peer->wY = 1;
  650.         else
  651.             view->Peer->wY = 0;
  652.         ConQuerySize(&W, &H);
  653.         if (ShowMenuBar)
  654.             H--;
  655.         if (ShowVScroll)
  656.             W--;
  657.         if (ShowHScroll)
  658.             H--;
  659.         view->ConSetSize(W, H);
  660.         InsertView(Top, view);
  661.         return 0;
  662.     }
  663. }
  664.  
  665. void GFrame::Update() {
  666.     GView *v = Active;
  667.     
  668.     UpdateMenu();
  669.     while (v) {
  670.         v->Update();
  671.         if ((ShowVScroll || ShowHScroll) && (v->Peer->sbVupdate || v->Peer->sbHupdate)) {
  672.             v->Peer->DrawScrollBar();
  673.             v->Peer->sbVupdate = 0;
  674.             v->Peer->sbHupdate = 0;
  675.         }
  676.         v = v->Next;
  677.         if (v == Active) 
  678.             break;
  679.     }
  680. }
  681.  
  682. void GFrame::UpdateMenu() {
  683.     if (ShowMenuBar)
  684.         DrawMenuBar();
  685. }
  686.  
  687. void GFrame::Repaint() {
  688.     GView *v = Active;
  689.     
  690.     if (ShowMenuBar)
  691.         DrawMenuBar();
  692.     while (v) {
  693.         v->Repaint();
  694.         if (ShowVScroll || ShowHScroll) {
  695.             v->Peer->DrawScrollBar();
  696.             v->Peer->sbVupdate = 0;
  697.             v->Peer->sbHupdate = 0;
  698.         }
  699.         v = v->Next;
  700.         if (v == Active) 
  701.             break;
  702.     }
  703. }
  704.  
  705. void GFrame::InsertView(GView *Prev, GView *view) {
  706.     if (!view) return ;
  707.     if (Prev) {
  708.         view->Prev = Prev;
  709.         view->Next = Prev->Next;
  710.         Prev->Next = view;
  711.         view->Next->Prev = view;
  712.     } else {
  713.         view->Prev = view->Next = view;
  714.         Top = view;
  715.     }
  716.     if (Active == 0) {
  717.         Active = view;
  718.         Active->Activate(1);
  719.     }
  720. }
  721.  
  722. void GFrame::RemoveView(GView *view) {
  723.     if (!view) return ;
  724.     
  725.     if (Active == view)
  726.         Active->Activate(0);
  727.     if (view->Next == view) {
  728.         Top = Active = 0;
  729.         delete this;
  730.     } else {
  731.         view->Next->Prev = view->Prev;
  732.         view->Prev->Next = view->Next;
  733.         
  734.         if (Top == view) {
  735.             Top = view->Next;
  736.             Top->Peer->wY -= view->Peer->wH;
  737.             Top->ConSetSize(Top->Peer->wW, Top->Peer->wH + view->Peer->wH + (ShowHScroll ? 1 : 0));
  738.         } else {
  739.             view->Prev->ConSetSize(view->Prev->Peer->wW,
  740.                                    view->Prev->Peer->wH + view->Peer->wH + (ShowHScroll ? 1 : 0));
  741.         }
  742.         
  743.         if (Active == view) {
  744.             Active = view->Prev;
  745.             Active->Activate(1);
  746.         }
  747.     }
  748. }
  749.  
  750. void GFrame::SelectNext(int back) {
  751.     GView *c = Active;
  752.     
  753.     if (c == 0 && Top == 0)
  754.         return;
  755.     
  756.     if (FocusCapture != 0)
  757.         return ;
  758.     
  759.     else if (c == 0)
  760.         c = Active = Top;
  761.     else
  762.         if (back) {
  763.             Active = Active->Prev;
  764.         } else {
  765.             Active = Active->Next;
  766.         }
  767.     if (c != Active) {
  768.         if (c)
  769.             c->Activate(0);
  770.         if (Active) 
  771.             Active->Activate(1);
  772.     }
  773. }
  774.  
  775. int GFrame::SelectView(GView *view) {
  776.     if (Top == 0)
  777.         return 0;
  778.     
  779.     if (FocusCapture != 0)
  780.         view = view;
  781.     
  782.     if (Active)
  783.         Active->Activate(0);
  784.     Active = view;
  785.     if (Active)
  786.         Active->Activate(1);
  787.     return 1;
  788. }
  789.  
  790. void GFrame::Resize(int width, int height) {
  791.     GView *V;
  792.     int count = 0;
  793.     
  794.     
  795.     V = Top;
  796.     while (V) {
  797.         count++;
  798.         if (V == Top) break;
  799.     }
  800.     if (height < 2 * count + 2 || width < 16) {
  801.         ::ConSetSize(16, 2 * count + 1);
  802.         return;
  803.     }
  804.     
  805.     if (!Top)
  806.         return;
  807.     
  808.     if (ShowVScroll)
  809.         width--;
  810.     if (ShowHScroll)
  811.         height--;
  812.     
  813. //    fprintf(stderr, "Resize: %d %d\n", width, height);
  814.     
  815.     V = Top->Prev;
  816.     
  817.     while (V != Top) {
  818.         int h, y;
  819.         
  820.         h = V->Peer->wH;
  821.         y = V->Peer->wY;
  822.         
  823.         if (y >= height - 2) {
  824.             y = height - 2;
  825.         }
  826.         if (y + h != height) {
  827.             h = height - y;
  828.         }
  829.         V->Peer->wY = y;
  830.         V->ConSetSize(width, h);
  831.         height = y;
  832.         V = V->Prev;
  833.     }
  834.     if (ShowMenuBar)
  835.         height--;
  836.     Top->ConSetSize(width, height);
  837.     Repaint();
  838.     //  fprintf(stderr, "Resize: %d %d Done\n", width, height);
  839. }
  840.  
  841. int GFrame::ExecMainMenu(char Sub) {
  842.     NextEvent.What = evCommand;
  843.     NextEvent.Msg.Command = cmMainMenu;
  844.     NextEvent.Msg.Param1 = Sub;
  845.     return 0;
  846. }
  847.  
  848. int GFrame::SetMenu(char *Name) {
  849.     if (Menu) free(Menu);
  850.     Menu = strdup(Name);
  851.     return 0;
  852. }
  853.  
  854. void GFrame::Show() {
  855. }
  856.  
  857. void GFrame::Activate() {
  858.     frames = this;
  859. }
  860.  
  861. int GUI::ConGrabEvents(TEventMask /*EventMask*/) {
  862.     return 0;
  863. }
  864.  
  865. void GUI::DispatchEvent(GFrame */*frame*/, GView *view, TEvent &Event) {
  866.     if (Event.What != evNone) {
  867.         if (view)
  868.             view->HandleEvent(Event);
  869.     }
  870. }
  871.  
  872. int GUI::ConGetEvent(TEventMask EventMask, TEvent *Event, int WaitTime, int Delete, GView **view) {
  873.     if (view)
  874.         *view = 0;
  875.     return ::ConGetEvent(EventMask, Event, WaitTime, Delete);
  876. }
  877.  
  878. int GUI::ConPutEvent(TEvent Event) {
  879.     return ::ConPutEvent(Event);
  880. }
  881.  
  882. int GUI::ConFlush(void) {
  883.     return 0;
  884. }
  885.  
  886. static inline int scrollBreak(TEvent &E)
  887. {
  888. #if defined(DOS) || defined(DOSP32)
  889.     // workaround until mouse code in con_dosx.cpp is finished
  890.     return (E.What != evMouseDown);
  891. #else
  892.     return (E.What == evMouseUp);
  893. #endif
  894. }
  895.  
  896. void HandleVScroll(GView *view, TEvent &E) {
  897.     int y; //, x
  898.     int wY, wH;
  899.     TEvent E1;
  900.     
  901.     //x = E.Mouse.X;
  902.     y = E.Mouse.Y;
  903.     wY = view->Peer->wY;
  904.     wH = view->Peer->wH;
  905.     if (y == wY) {
  906.         do {
  907.             E1.What = evCommand;
  908.             E1.Msg.View = view;
  909.             E1.Msg.Command = cmVScrollUp;
  910.             gui->DispatchEvent(frames, view, E1);
  911.             frames->Update();
  912.             do {
  913.                 ConGetEvent(evMouse | evNotify, &E, -1, 1);
  914.                 if (E.What & evNotify)
  915.                     gui->DispatchEvent(frames, view, E);
  916.             } while (E.What & evNotify);
  917.             if (scrollBreak(E)) break;
  918.         } while (1);
  919.     } else if (y == wY + wH - 1) {
  920.         do {
  921.             E1.What = evCommand;
  922.             E1.Msg.View = view;
  923.             E1.Msg.Command = cmVScrollDown;
  924.             gui->DispatchEvent(frames, view, E1);
  925.             frames->Update();
  926.             do {
  927.                 ConGetEvent(evMouse | evNotify, &E, -1, 1);
  928.                 if (E.What & evNotify)
  929.                     gui->DispatchEvent(frames, view, E);
  930.             } while (E.What & evNotify);
  931.             if (scrollBreak(E)) break;
  932.         } while (1);
  933.     } else if (y < wY + view->Peer->SbVBegin + 1) {
  934.         do {
  935.             E1.What = evCommand;
  936.             E1.Msg.View = view;
  937.             E1.Msg.Command = cmVScrollPgUp;
  938.             gui->DispatchEvent(frames, view, E1);
  939.             frames->Update();
  940.             do {
  941.                 ConGetEvent(evMouse | evNotify, &E, -1, 1);
  942.                 if (E.What & evNotify)
  943.                     gui->DispatchEvent(frames, view, E);
  944.             } while (E.What & evNotify);
  945.             if (scrollBreak(E)) break;
  946.         } while (1);
  947.     } else if (y > wY + view->Peer->SbVEnd + 1) {
  948.         do {
  949.             E1.What = evCommand;
  950.             E1.Msg.View = view;
  951.             E1.Msg.Command = cmVScrollPgDn;
  952.             gui->DispatchEvent(frames, view, E1);
  953.             frames->Update();
  954.             do {
  955.                 ConGetEvent(evMouse | evNotify, &E, -1, 1);
  956.                 if (E.What & evNotify)
  957.                     gui->DispatchEvent(frames, view, E);
  958.             } while (E.What & evNotify);
  959.             if (scrollBreak(E)) break;
  960.         } while (1);
  961.     } else {
  962.         int delta = y - 1 - view->Peer->SbVBegin - wY;
  963.         
  964.         do {
  965.             E1.What = evCommand;
  966.             E1.Msg.View = view;
  967.             E1.Msg.Command = cmVScrollMove;
  968.             E1.Msg.Param1 = (E.Mouse.Y - wY - 1 - delta + 1) * view->Peer->sbVtotal / (wH - 2);
  969. //            printf("YPos = %d %d %d \n\x7", E.Mouse.Y, wY, delta);
  970.             gui->DispatchEvent(frames, view, E1);
  971.             frames->Update();
  972.             do {
  973.                 ConGetEvent(evMouse | evNotify, &E, -1, 1);
  974.                 if (E.What & evNotify)
  975.                     gui->DispatchEvent(frames, view, E);
  976.             } while (E.What & evNotify);
  977.             if (scrollBreak(E)) break;
  978.         } while (1);
  979.     }
  980.     E.What = evNone;
  981. }
  982.  
  983. void HandleHScroll(GView *view, TEvent &E) {
  984.     int x; //, x
  985.     int wX, wW;
  986.     TEvent E1;
  987.     
  988.     //x = E.Mouse.X;
  989.     x = E.Mouse.X;
  990.     wX = view->Peer->wX;
  991.     wW = view->Peer->wW;
  992.     if (x == wX) {
  993.         do {
  994.             E1.What = evCommand;
  995.             E1.Msg.View = view;
  996.             E1.Msg.Command = cmHScrollLeft;
  997.             gui->DispatchEvent(frames, view, E1);
  998.             frames->Update();
  999.             do {
  1000.                 ConGetEvent(evMouse | evNotify, &E, -1, 1);
  1001.                 if (E.What & evNotify)
  1002.                     gui->DispatchEvent(frames, view, E);
  1003.             } while (E.What & evNotify);
  1004.             if (scrollBreak(E)) break;
  1005.         } while (1);
  1006.     } else if (x == wX + wW - 1) {
  1007.         do {
  1008.             E1.What = evCommand;
  1009.             E1.Msg.View = view;
  1010.             E1.Msg.Command = cmHScrollRight;
  1011.             gui->DispatchEvent(frames, view, E1);
  1012.             frames->Update();
  1013.             do {
  1014.                 ConGetEvent(evMouse | evNotify, &E, -1, 1);
  1015.                 if (E.What & evNotify)
  1016.                     gui->DispatchEvent(frames, view, E);
  1017.             } while (E.What & evNotify);
  1018.             if (scrollBreak(E)) break;
  1019.         } while (1);
  1020.     } else if (x < wX + view->Peer->SbHBegin + 1) {
  1021.         do {
  1022.             E1.What = evCommand;
  1023.             E1.Msg.View = view;
  1024.             E1.Msg.Command = cmHScrollPgLt;
  1025.             gui->DispatchEvent(frames, view, E1);
  1026.             frames->Update();
  1027.             do {
  1028.                 ConGetEvent(evMouse | evNotify, &E, -1, 1);
  1029.                 if (E.What & evNotify)
  1030.                     gui->DispatchEvent(frames, view, E);
  1031.             } while (E.What & evNotify);
  1032.             if (scrollBreak(E)) break;
  1033.         } while (1);
  1034.     } else if (x > wX + view->Peer->SbHEnd + 1) {
  1035.         do {
  1036.             E1.What = evCommand;
  1037.             E1.Msg.View = view;
  1038.             E1.Msg.Command = cmHScrollPgRt;
  1039.             gui->DispatchEvent(frames, view, E1);
  1040.             frames->Update();
  1041.             do {
  1042.                 ConGetEvent(evMouse | evNotify, &E, -1, 1);
  1043.                 if (E.What & evNotify)
  1044.                     gui->DispatchEvent(frames, view, E);
  1045.             } while (E.What & evNotify);
  1046.             if (scrollBreak(E)) break;
  1047.         } while (1);
  1048.     } else {
  1049.         int delta = x - 1 - view->Peer->SbHBegin - wX;
  1050.         
  1051.         do {
  1052.             E1.What = evCommand;
  1053.             E1.Msg.View = view;
  1054.             E1.Msg.Command = cmHScrollMove;
  1055.             E1.Msg.Param1 = (E.Mouse.X - wX - 1 - delta + 1) * view->Peer->sbHtotal / (wW - 2);
  1056. //            printf("YPos = %d %d %d \n\x7", E.Mouse.Y, wY, delta);
  1057.             gui->DispatchEvent(frames, view, E1);
  1058.             frames->Update();
  1059.             do {
  1060.                 ConGetEvent(evMouse | evNotify, &E, -1, 1);
  1061.                 if (E.What & evNotify)
  1062.                     gui->DispatchEvent(frames, view, E);
  1063.             } while (E.What & evNotify);
  1064.             if (scrollBreak(E)) break;
  1065.         } while (1);
  1066.     }
  1067.     E.What = evNone;
  1068. }
  1069.  
  1070. void GUI::ProcessEvent() {
  1071.     TEvent E;
  1072.     
  1073.     E = NextEvent;
  1074.     if (E.What != evNone) {
  1075.         NextEvent.What = evNone;
  1076.     }
  1077.     if (E.What == evNone) {
  1078.         if (ConGetEvent(evMouse | evCommand | evKeyboard, &E, 0, 1, 0) == -1)
  1079.             //            return -1
  1080.             ;
  1081.     }
  1082.     if (E.What == evNone) {
  1083.         frames->Update();
  1084.     again:
  1085.         if (ConGetEvent(evMouse | evCommand | evKeyboard, &E, -1, 1, 0) == -1)
  1086.             //    return -1
  1087.             ;
  1088.         if (E.What == evMouseMove && E.Mouse.Buttons == 0)
  1089.             goto again;
  1090.     }
  1091.     if (E.What != evNone) {
  1092.         GView *view = frames->Active;
  1093.  
  1094.         if (E.What & evMouse) {
  1095.             if (E.What == evMouseDown && E.Mouse.Y == 0 && ShowMenuBar &&
  1096.                 MouseCapture == 0 && FocusCapture == 0)
  1097.             {
  1098.                 frames->Update(); // sync before menu
  1099.                 if (ExecMainMenu(E, 0) == -1) {
  1100.                     if (E.What == evCommand && E.Msg.Command == cmResize) {
  1101.                         int X, Y;
  1102.  
  1103.                         ConQuerySize(&X, &Y);
  1104.                         frames->Resize(X, Y);
  1105.                     }
  1106.                     E.What = evNone;
  1107.                 }
  1108. //                fprintf(stderr, "Command got = %d\n", E.Msg.Command);
  1109.             }
  1110.             if (E.What == evMouseDown && MouseCapture == 0 && FocusCapture == 0) {
  1111.                 GView *V = frames->Active;
  1112.                 
  1113.                 while (V) {
  1114.                     if (E.Mouse.Y >= V->Peer->wY &&
  1115.                         E.Mouse.Y <  V->Peer->wY + V->Peer->wH + (ShowHScroll ? 1 : 0))
  1116.                     {
  1117.                         frames->SelectView(V);
  1118.                         view = V;
  1119.                         break;
  1120.                     }
  1121.                     V = V->Next;
  1122.                     if (V == frames->Active)
  1123.                         break;
  1124.                 }
  1125.             }
  1126.             if (ShowVScroll && ShowHScroll && E.What == evMouseDown &&
  1127.                 MouseCapture == 0 && FocusCapture == 0 &&
  1128.                 E.Mouse.Y == view->Peer->wY + view->Peer->wH &&
  1129.                 E.Mouse.X == view->Peer->wX + view->Peer->wW)
  1130.             {
  1131.             } else {
  1132.                 if (ShowVScroll && E.What == evMouseDown && MouseCapture == 0 && FocusCapture == 0 &&
  1133.                     E.Mouse.X == view->Peer->wX + view->Peer->wW)
  1134.                 {
  1135.                     HandleVScroll(view, E);
  1136.                     return ;
  1137.                 }
  1138.                 if (ShowHScroll && E.What == evMouseDown && MouseCapture == 0 && FocusCapture == 0 &&
  1139.                     E.Mouse.Y == view->Peer->wY + view->Peer->wH)
  1140.                 {
  1141.                     HandleHScroll(view, E);
  1142.                     return ;
  1143.                 }
  1144.             }
  1145.             if (E.What & evMouse) {
  1146.                 E.Mouse.Y -= view->Peer->wY;
  1147.                 E.Mouse.X -= view->Peer->wX;
  1148.             }
  1149.         }
  1150.         if (E.What == evCommand) {
  1151.             switch (E.Msg.Command) {
  1152.             case cmResize: 
  1153.                 {
  1154.                     int X, Y;
  1155.  
  1156.                     ConQuerySize(&X, &Y);
  1157.                     frames->Resize(X, Y);
  1158.                 }
  1159.                 break;
  1160.             case cmMainMenu:
  1161.                 {
  1162.                     char Sub = (char)E.Msg.Param1;
  1163.  
  1164.                     frames->Update(); // sync before menu
  1165.                     if (::ExecMainMenu(E, Sub) != 1) {;
  1166.                         if (E.What == evCommand && E.Msg.Command == cmResize) {
  1167.                             int X, Y;
  1168.  
  1169.                             ConQuerySize(&X, &Y);
  1170.                             frames->Resize(X, Y);
  1171.                         }
  1172.                         E.What = evNone;
  1173.                     }
  1174.                 }
  1175.                 break;
  1176.             case cmPopupMenu:
  1177.                 {
  1178.                     int id = E.Msg.Param1;
  1179.                     int Cols, Rows;
  1180.                     
  1181.                     if (id == -1) return;
  1182.                     frames->ConQuerySize(&Cols, &Rows);
  1183.                     int x = Cols / 2, y = Rows / 2;
  1184.                     ::ConQueryMousePos(&x, &y);
  1185.                     
  1186.                     frames->Update(); // sync before menu
  1187.                     if (::ExecVertMenu(x, y, id, E, 0) != 1) {
  1188.                         if (E.What == evCommand && E.Msg.Command == cmResize) {
  1189.                             int X, Y;
  1190.  
  1191.                             ConQuerySize(&X, &Y);
  1192.                             frames->Resize(X, Y);
  1193.                         }
  1194.                         E.What = evNone;
  1195.                     }
  1196.                 }
  1197.                 break;
  1198.             }
  1199.         }
  1200.         if (E.What != evNone)
  1201.             DispatchEvent(frames, view, E);
  1202.     }
  1203. }
  1204.  
  1205. int GUI::Run() {
  1206.     if (Start(fArgc, fArgv) == 0) {
  1207.         doLoop = 1;
  1208.         while (doLoop)
  1209.             ProcessEvent();
  1210.         Stop();
  1211.         return 0;
  1212.     }
  1213.     return 1;
  1214. }
  1215.  
  1216. int GUI::multiFrame() {
  1217.     return 0;
  1218. }
  1219.  
  1220. void DieError(int rc, char *msg, ...) {
  1221.     va_list ap;
  1222.     
  1223.     va_start(ap, msg);
  1224.     vfprintf(stderr, msg, ap);
  1225.     va_end(ap);
  1226.     fprintf(stderr, "\n");
  1227.     exit(rc);
  1228. }
  1229.