/ source / blood / src / gui.cpp
gui.cpp
   1  #include <stdio.h>
   2  #include <stdlib.h>
   3  #include <string.h>
   4  #include "compat.h"
   5  #include "baselayer.h"
   6  #include "build.h"
   7  #include "common_game.h"
   8  #include "gfx.h"
   9  #include "globals.h"
  10  #include "gui.h"
  11  #include "keyboard.h"
  12  #include "resource.h"
  13  #include "screen.h"
  14  #include "music.h"
  15  
  16  
  17  Resource gGuiRes;
  18  
  19  QFONT* pFont;
  20  
  21  QBITMAP* pMouseCursor;
  22  
  23  inline char ScanToAsciiShifted(int scan)
  24  {
  25      if (scan < 128)
  26          return g_keyAsciiTableShift[scan];
  27      return 0;
  28  }
  29  
  30  int blinkClock;
  31  
  32  void SetBlinkOn(void)
  33  {
  34      blinkClock = 0;
  35  }
  36  
  37  void SetBlinkOff(void)
  38  {
  39      blinkClock = 60;
  40  }
  41  
  42  char IsBlinkOn(void)
  43  {
  44      return blinkClock < 60;
  45  }
  46  
  47  void UpdateBlinkClock(int n)
  48  {
  49      blinkClock += n;
  50      while (blinkClock >= 100)
  51          blinkClock -= 100;
  52  }
  53  
  54  void CenterLabel(int a1, int a2, const char *a3, int a4)
  55  {
  56      if (pFont)
  57          a2 -= pFont->at13/2;
  58      
  59      a1 -= gfxGetLabelLen(a3, pFont) / 2;
  60      gfxDrawLabel(a1, a2, a4, a3, pFont);
  61  }
  62  
  63  void DrawBevel(int x0, int y0, int x1, int y1, int c0, int c1)
  64  {
  65      gColor = c0;
  66      gfxHLine(y0, x0, x1 - 2);
  67      gfxVLine(x0, y0 + 1, y1 - 2);
  68      gColor = c1;
  69      gfxHLine(y1 - 1, x0 + 1, x1 - 1);
  70      gfxVLine(x1 - 1, y0 + 1, y1 - 2);
  71  }
  72  
  73  void DrawRect(int x0, int y0, int x1, int y1, int c)
  74  {
  75      gColor = c;
  76      gfxHLine(y0, x0, x1 - 1);
  77      gfxHLine(y1 - 1, x0, x1 - 1);
  78      gfxVLine(x0, y0 + 1, y1 - 2);
  79      gfxVLine(x1 - 1, y0 + 1, y1 - 2);
  80  }
  81  
  82  void DrawButtonFace(int x0, int y0, int x1, int y1, char a5)
  83  {
  84      gColor = gStdColor[20];
  85      gfxFillBox(x0, y0, x1, y1);
  86  
  87      if (a5)
  88      {
  89          gColor = gStdColor[26];
  90          gfxHLine(y0, x0, x1 - 1);
  91          gfxVLine(x0, y0 + 1, y1 - 1);
  92          gColor = gStdColor[24];
  93          gfxHLine(y0 + 1, x0 + 1, x1 - 1);
  94          gfxVLine(x0 + 1, y0 + 2, y1 - 1);
  95          DrawBevel(x0+2, y0+2, x1, y1, gStdColor[19], gStdColor[22]);
  96      }
  97      else
  98      {
  99          DrawBevel(x0, y0, x1, y1, gStdColor[16], gStdColor[24]);
 100          DrawBevel(x0+1, y0+1, x1-1, y1-1, gStdColor[18], gStdColor[22]);
 101      }
 102  }
 103  
 104  void DrawMouseCursor(int x, int y)
 105  {
 106      dassert(pMouseCursor != NULL);
 107  
 108      gfxDrawBitmap(pMouseCursor, x, y);
 109  }
 110  
 111  char GetHotKey(const char *pzLabel)
 112  {
 113      for (const char* s = pzLabel; *s != 0; s++)
 114      {
 115          if (*s == '&')
 116              return (char)toupper(*(s+1));
 117      }
 118      return 0;
 119  }
 120  
 121  Label::Label(int a1, int a2, const char* a3) : Widget(a1, a2, 0, 0)
 122  {
 123      at8 = strlen(a3);
 124      strcpy(at24, a3);
 125  }
 126  
 127  void Label::Paint(int x, int y, char)
 128  {
 129      gfxDrawLabel(x, y, gStdColor[0], at24, pFont);
 130  }
 131  
 132  Container::Container(int a1, int a2, int a3, int a4) : Widget(a1, a2, a3, a4)
 133  {
 134      at1e = 1;
 135      at24 = 0;
 136      at25 = MODAL_RESULT_0;
 137  
 138      at2e.at10 = at2e.at14 = &at2e;
 139      at26 = &at2e;
 140  
 141      at2a = NULL;
 142  }
 143  
 144  Container::~Container()
 145  {
 146      for (Widget* pWidget = at2e.at14; pWidget != &at2e; pWidget = at2e.at14)
 147      {
 148          Remove(pWidget);
 149          delete pWidget;
 150      }
 151  }
 152  
 153  char Container::SetFocus(int a1)
 154  {
 155      do
 156      {
 157          if (at26->at1e && ((Container*)at26)->SetFocus(a1))
 158              return 1;
 159          if (a1 > 0)
 160              at26 = at26->at14;
 161          else
 162              at26 = at26->at10;
 163          if (at26 == &at2e)
 164              return 0;
 165      } while (!at26->at1c);
 166      return 1;
 167  }
 168  
 169  void Container::Insert(Widget* widget)
 170  {
 171      dassert(widget != NULL);
 172      widget->at10 = at2e.at10;
 173      widget->at14 = &at2e;
 174      widget->at10->at14 = widget;
 175      widget->at14->at10 = widget;
 176      widget->at18 = this;
 177  }
 178  
 179  void Container::Remove(Widget* widget)
 180  {
 181      dassert(widget != NULL);
 182      widget->at10->at14 = widget->at14;
 183      widget->at14->at10 = widget->at10;
 184  }
 185  
 186  void Container::Paint(int x, int y, char a3)
 187  {
 188      UNREFERENCED_PARAMETER(a3);
 189      for (Widget* pWidget = at2e.at14; pWidget != &at2e; pWidget = pWidget->at14)
 190      {
 191          pWidget->Paint(x + pWidget->at0, y + pWidget->at4, at26 == pWidget);
 192      }
 193  }
 194  
 195  void Container::HandleEvent(GEVENT* event)
 196  {
 197      if (event->at0 & GEVENT_TYPE_MOUSE_MASK)
 198      {
 199          event->at6.mouse.at8 -= at0;
 200          event->at6.mouse.atc -= at4;
 201          if (event->at0 == 1)
 202          {
 203              at2a = NULL;
 204              for (Widget* pWidget = at2e.at10; pWidget != &at2e; pWidget = pWidget->at10)
 205              {
 206                  if (pWidget->Inside(event->at6.mouse.at8, event->at6.mouse.atc))
 207                  {
 208                      at2a = pWidget;
 209                      if (pWidget->at1c)
 210                          at26 = pWidget;
 211                      break;
 212                  }
 213              }
 214          }
 215          if (at2a)
 216              at2a->HandleEvent(event);
 217          return;
 218      }
 219      else if (event->at0 == GEVENT_TYPE_KEYBOARD)
 220      {
 221          if (event->at6.keyboard.at2.bits.at2 && g_keyAsciiTableShift[event->at6.keyboard.at1])
 222          {
 223              for (Widget* pWidget = at2e.at10; pWidget != &at2e; pWidget = pWidget->at10)
 224              {
 225                  if (pWidget->at1f == g_keyAsciiTableShift[event->at6.keyboard.at1] && pWidget->at1c)
 226                  {
 227                      at26 = pWidget;
 228                      at26->HandleEvent(event);
 229                      return;
 230                  }
 231              }
 232          }
 233          at26->HandleEvent(event);
 234  
 235          if (event->at0 != GEVENT_TYPE_NONE)
 236          {
 237              for (Widget* pWidget = at2e.at10; pWidget != &at2e; pWidget = pWidget->at10)
 238              {
 239                  if (pWidget->at1f == g_keyAsciiTableShift[event->at6.keyboard.at1] && pWidget->at1c)
 240                  {
 241                      at26 = pWidget;
 242                      at26->HandleEvent(event);
 243                      return;
 244                  }
 245              }
 246          }
 247      }
 248  }
 249  
 250  void Container::EndModal(MODAL_RESULT result)
 251  {
 252      if (at24)
 253      {
 254          at24 = 0;
 255          at25 = result;
 256          return;
 257      }
 258      at18->EndModal(result);
 259  }
 260  
 261  void Panel::Paint(int x, int y, char a3)
 262  {
 263      gColor = gStdColor[20];
 264      gfxFillBox(x, y, x + at8, y + atc);
 265      int j = 0;
 266      for (int i = klabs(at52); i > 0; i--, j++)
 267      {
 268          if (at52 > 0)
 269          {
 270              DrawBevel(x+j,y+j,x+at8-j,y+atc-j, gStdColor[16], gStdColor[24]);
 271          }
 272          else
 273          {
 274              DrawBevel(x+j,y+j,x+at8-j,y+atc-j, gStdColor[24], gStdColor[16]);
 275          }
 276      }
 277      j += at56;
 278      for (int i = klabs(at5a); i > 0; i--, j++)
 279      {
 280          if (at5a > 0)
 281          {
 282              DrawBevel(x+j,y+j,x+at8-j,y+atc-j, gStdColor[16], gStdColor[24]);
 283          }
 284          else
 285          {
 286              DrawBevel(x+j,y+j,x+at8-j,y+atc-j, gStdColor[24], gStdColor[16]);
 287          }
 288      }
 289      Container::Paint(x, y, a3);
 290  }
 291  
 292  TitleBar::TitleBar(int a1, int a2, int a3, int a4, const char *a5) : Widget(a1, a2, a3, a4)
 293  {
 294      strcpy(at24, a5);
 295      at124 = strlen(a5);
 296  }
 297  
 298  void TitleBar::Paint(int x, int y, char a3)
 299  {
 300      UNREFERENCED_PARAMETER(a3);
 301      gColor = gStdColor[1];
 302      gfxFillBox(x, y, x + at8, y + atc);
 303      DrawBevel(x, y, x + at8, y + atc, gStdColor[9], gStdColor[30]);
 304      CenterLabel(x + at8 / 2, y + atc / 2, at24, gStdColor[15]);
 305  }
 306  
 307  void TitleBar::HandleEvent(GEVENT *event)
 308  {
 309      if (event->at0 & GEVENT_TYPE_MOUSE_MASK)
 310      {
 311          if (event->at6.mouse.at4 == 0)
 312          {
 313              if (event->at0 == GEVENT_TYPE_MOUSE_8)
 314              {
 315                  at18->at0 += event->at6.mouse.at10;
 316                  at18->at4 += event->at6.mouse.at14;
 317                  event->at0 = GEVENT_TYPE_NONE;
 318              }
 319          }
 320      }
 321  }
 322  
 323  Win::Win(int a1, int a2, int a3, int a4, const char* a5) : Panel(a1, a2, a3, a4, 1, 1, -1)
 324  {
 325      at62 = new TitleBar(3, 3, a3-6, 12, a5);
 326      at5e = new Container(3, 15, a3-6, a4-18);
 327      Insert(at62);
 328      Insert(at5e);
 329      at2a = NULL;
 330  }
 331  
 332  Button::Button(int a1, int a2, int a3, int a4, MODAL_RESULT a5) : Widget(a1, a2, a3, a4)
 333  {
 334      at24 = a5;
 335      at25 = NULL;
 336      at29 = 0;
 337  }
 338  
 339  Button::Button(int a1, int a2, int a3, int a4, void (*a5)(Widget*)) : Widget(a1, a2, a3, a4)
 340  {
 341      at24 = MODAL_RESULT_0;
 342      at25 = a5;
 343      at29 = 0;
 344  }
 345  
 346  void Button::Paint(int x, int y, char a3)
 347  {
 348      UNREFERENCED_PARAMETER(a3);
 349      gColor = gStdColor[0];
 350      gfxHLine(y, x + 1, x + at8 - 2);
 351      gfxHLine(y + atc - 1, x + 1, x + at8 - 2);
 352      gfxVLine(x, y + 1, y + atc - 2);
 353      gfxVLine(x + at8 - 1, y + 1, y + atc - 2);
 354      DrawButtonFace(x + 1, y + 1, x + at8 - 1, y + atc - 1, at29);
 355  }
 356  
 357  void Button::HandleEvent(GEVENT* event)
 358  {
 359      if (event->at0 == GEVENT_TYPE_KEYBOARD)
 360      {
 361          if (event->at6.keyboard.at0 == ' ' || ScanToAsciiShifted(event->at6.keyboard.at1) == at1f)
 362          {
 363              at29 = !at29;
 364              if (at25)
 365                  at25(this);
 366              if (at24)
 367                  EndModal(at24);
 368              event->at0 = GEVENT_TYPE_NONE;
 369          }
 370      }
 371      else if ((event->at0 & GEVENT_TYPE_MOUSE_MASK) && event->at6.mouse.at4 == 0)
 372      {
 373          switch (event->at0)
 374          {
 375          case GEVENT_TYPE_MOUSE_1:
 376              at29 = 1;
 377              at0 = GEVENT_TYPE_NONE;
 378              break;
 379          case GEVENT_TYPE_MOUSE_8:
 380              at29 = Inside(event->at6.mouse.at8, event->at6.mouse.atc);
 381              at0 = GEVENT_TYPE_NONE;
 382              break;
 383          case GEVENT_TYPE_MOUSE_2:
 384              at29 = 0;
 385              if (Inside(event->at6.mouse.at8, event->at6.mouse.atc))
 386              {
 387                  if (at25)
 388                      at25(this);
 389                  if (at24)
 390                      EndModal(at24);
 391              }
 392              at0 = GEVENT_TYPE_NONE;
 393              break;
 394          default:
 395              break;
 396          }
 397      }
 398  }
 399  
 400  TextButton::TextButton(int a1, int a2, int a3, int a4, const char *a5, MODAL_RESULT a6) : Button(a1, a2, a3, a4, a6)
 401  {
 402      at2a = a5;
 403      at1f = GetHotKey(a5);
 404      at1c = 1;
 405  }
 406  
 407  void TextButton::Paint(int x, int y, char a3)
 408  {
 409      gColor = gStdColor[0];
 410      gfxHLine(y + 1, x + 2, x + at8 - 3);
 411      gfxHLine(y + atc - 2, y + 2, x + at8 - 3);
 412      gfxVLine(x + 1, y + 2, y + atc - 3);
 413      gfxVLine(x + at8 - 2, y + 2, y + atc - 3);
 414      if (a3)
 415      {
 416          gColor = gStdColor[15];
 417          gfxHLine(y, x + 1, x + at8 - 2);
 418          gfxHLine(y + atc - 1, x + 1, x + at8 - 2);
 419          gfxVLine(x, y + 1, y + atc - 2);
 420          gfxVLine(x + at8 - 1, y + 1, y + atc - 2);
 421          gfxPixel(x + 1, y + 1);
 422          gfxPixel(x + at8 - 2, y + 1);
 423          gfxPixel(x + 1, y + atc - 2);
 424          gfxPixel(x + at8 - 2, y + atc - 2);
 425      }
 426      DrawButtonFace(x + 2, y + 2, x + at8 - 2, y + atc - 2, at29);
 427      if (at29)
 428          CenterLabel(x + at8 / 2 + 1, y + atc / 2 + 1, at2a, gStdColor[0]);
 429      else
 430          CenterLabel(x + at8 / 2, y + atc / 2, at2a, gStdColor[0]);
 431  }
 432  
 433  void TextButton::HandleEvent(GEVENT* event)
 434  {
 435      if (event->at0 == GEVENT_TYPE_KEYBOARD && ScanToAsciiShifted(event->at6.keyboard.at1) == at1f)
 436      {
 437          at29 = !at29;
 438          if (at25)
 439              at25(this);
 440          if (at24)
 441              EndModal(at24);
 442          event->at0 = GEVENT_TYPE_NONE;
 443      }
 444      Button::HandleEvent(event);
 445  }
 446  
 447  void BitButton::Paint(int x, int y, char a3)
 448  {
 449      UNREFERENCED_PARAMETER(a3);
 450      gColor = gStdColor[0];
 451      gfxHLine(y, x + 1, x + at8 - 2);
 452      gfxHLine(y + atc -1, x + 1, x + at8 - 2);
 453      gfxVLine(x, y + 1, y + atc - 2);
 454      gfxVLine(x + at8 - 1, y + 1, y + atc - 2);
 455      DrawButtonFace(x + 1, y + 1, x + at8 - 1, y + atc - 1, at29);
 456  
 457      int bx = x + at8 / 2;
 458      int by = y + atc / 2;
 459      QBITMAP* pQBM = (QBITMAP*)gGuiRes.Load(bitmap);
 460  
 461      if (at29)
 462          gfxDrawBitmap(pQBM, bx - pQBM->at2 / 2 + 1, by - pQBM->at4 / 2 + 1);
 463      else
 464          gfxDrawBitmap(pQBM, bx - pQBM->at2 / 2, by - pQBM->at4 / 2);
 465  }
 466  
 467  EditText::EditText(int a1, int a2, int a3, int a4, const char *a5) : Widget(a1,a2,a3,a4)
 468  {
 469      at1c = 1;
 470      strcpy(at24, a5);
 471      at128 = at124 = strlen(a5);
 472      at12c = a3 / 8 - 1;
 473  }
 474  
 475  void EditText::Paint(int x, int y, char a3)
 476  {
 477      DrawBevel(x, y, x + at8 - 1, y + atc - 1, gStdColor[24], gStdColor[16]);
 478      DrawRect(x + 1, y + 1, x + at8 - 2, y + atc - 2, gStdColor[0]);
 479      gColor = gStdColor[a3 ? 15 : 20];
 480      gfxFillBox(x + 2, y + 2, x + at8 - 3, y + atc - 3);
 481      gfxDrawText(x + 3, y + atc / 2 - 4, gStdColor[0], at24, pFont);
 482  
 483      if (a3 && IsBlinkOn())
 484      {
 485          gColor = gStdColor[0];
 486          y += atc / 2;
 487          gfxVLine(x + gfxGetTextNLen(at24, pFont, at128) + 3, y - 4, y + 3);
 488      }
 489  }
 490  
 491  void EditText::HandleEvent(GEVENT *event)
 492  {
 493      if (event->at0 & GEVENT_TYPE_MOUSE_MASK)
 494      {
 495          if (event->at6.mouse.at4 == 0)
 496          {
 497              switch (event->at0)
 498              {
 499              case GEVENT_TYPE_MOUSE_1:
 500              case GEVENT_TYPE_MOUSE_8:
 501                  at128 = gfxFindTextPos(at24, pFont, event->at6.mouse.at8 - at0);
 502                  SetBlinkOn();
 503                  event->at0 = GEVENT_TYPE_NONE;
 504                  break;
 505              default:
 506                  break;
 507              }
 508          }
 509      }
 510      else if (event->at0 == GEVENT_TYPE_KEYBOARD)
 511      {
 512          switch (event->at6.keyboard.at1)
 513          {
 514          case sc_BackSpace:
 515              if (at128 > 0)
 516              {
 517                  memmove(at24+at128-1, at24+at128, at124-at128);
 518                  at128--;
 519                  at124--;
 520                  at24[at124] = 0;
 521              }
 522              event->at0 = GEVENT_TYPE_NONE;
 523              SetBlinkOn();
 524              break;
 525          case sc_Delete:
 526              if (at128 < at124)
 527              {
 528                  at124--;
 529                  memmove(at24+at128, at24+at128+1, at124-at128);
 530                  at24[at124] = 0;
 531              }
 532              event->at0 = GEVENT_TYPE_NONE;
 533              SetBlinkOn();
 534              break;
 535          case sc_LeftArrow:
 536              if (at128 > 0)
 537                  at128--;
 538              event->at0 = GEVENT_TYPE_NONE;
 539              SetBlinkOn();
 540              break;
 541          case sc_RightArrow:
 542              if (at128 < at124)
 543                  at128++;
 544              event->at0 = GEVENT_TYPE_NONE;
 545              SetBlinkOn();
 546              break;
 547          case sc_Home:
 548              at128 = 0;
 549              event->at0 = GEVENT_TYPE_NONE;
 550              SetBlinkOn();
 551              break;
 552          case sc_End:
 553              at128 = at124;
 554              event->at0 = GEVENT_TYPE_NONE;
 555              SetBlinkOn();
 556              break;
 557          default:
 558              if (event->at6.keyboard.at0)
 559              {
 560                  if (at124 < at12c)
 561                  {
 562                      memmove(at24+at128+1,at24+at128,at124-at128);
 563                      at24[at128++] = event->at6.keyboard.at0;
 564                      at124++;
 565                      at24[at124] = 0;
 566                  }
 567                  event->at0 = GEVENT_TYPE_NONE;
 568              }
 569              SetBlinkOn();
 570              break;
 571          }
 572      }
 573  }
 574  
 575  EditNumber::EditNumber(int a1, int a2, int a3, int a4, int a5) : EditText(a1, a2, a3, a4, "")
 576  {
 577      at130 = a5;
 578      snprintf(at24, 0x100, "%i", a5);
 579      at128 = at124 = strlen(at24);
 580  }
 581  
 582  void EditNumber::HandleEvent(GEVENT *event)
 583  {
 584      if (event->at0 == GEVENT_TYPE_KEYBOARD)
 585      {
 586          switch (event->at6.keyboard.at1)
 587          {
 588          case sc_Minus:
 589              if (at128 == 0 && at24[0] != '-' && at124 < at12c)
 590              {
 591                  memmove(at24+1, at24, at124);
 592                  at24[at128++] = '-';
 593                  at124++;
 594                  at24[at124] = 0;
 595              }
 596              event->at0 = GEVENT_TYPE_NONE;
 597              break;
 598          case sc_BackSpace:
 599              break;
 600          case sc_Delete:
 601              break;
 602          case sc_LeftArrow:
 603              break;
 604          case sc_RightArrow:
 605              break;
 606          case sc_Home:
 607              break;
 608          case sc_End:
 609              break;
 610          default:
 611              if (event->at6.keyboard.at0)
 612              {
 613                  if (event->at6.keyboard.at0 >= '0' && event->at6.keyboard.at0 <= '9' && at124 < at12c)
 614                  {
 615                      memmove(at24+at128+1,at24+at128,at124-at128);
 616                      at24[at128++] = event->at6.keyboard.at0;
 617                      at124++;
 618                      at24[at124] = 0;
 619                  }
 620                  event->at0 = GEVENT_TYPE_NONE;
 621              }
 622              break;
 623          }
 624      }
 625      EditText::HandleEvent(event);
 626      at130 = atoi(at24);
 627  }
 628  
 629  void ThumbButton::HandleEvent(GEVENT* event)
 630  {
 631      if (event->at0 & GEVENT_TYPE_MOUSE_MASK)
 632      {
 633          if (event->at6.mouse.at4 == 0)
 634          {
 635              switch (event->at0)
 636              {
 637              case GEVENT_TYPE_MOUSE_8:
 638                  at4 = ClipRange(event->at6.mouse.atc-atc/2, 10, at18->atc-10-atc);
 639                  break;
 640              case GEVENT_TYPE_MOUSE_1:
 641                  at29 = 1;
 642                  break;
 643              case GEVENT_TYPE_MOUSE_2:
 644                  at29 = 0;
 645                  break;
 646              default:
 647                  break;
 648              }
 649          }
 650      }
 651  }
 652  
 653  void ScrollButton::HandleEvent(GEVENT* event)
 654  {
 655      if (event->at0 & GEVENT_TYPE_MOUSE_MASK)
 656      {
 657          if (event->at6.mouse.at4 == 0)
 658          {
 659              switch (event->at0)
 660              {
 661              case GEVENT_TYPE_MOUSE_1:
 662                  at29 = 1;
 663                  if (at25)
 664                      at25(this);
 665                  break;
 666              case GEVENT_TYPE_MOUSE_8:
 667                  at29 = Inside(event->at6.mouse.at8, event->at6.mouse.atc);
 668                  break;
 669              case GEVENT_TYPE_MOUSE_4:
 670                  if (at29 || at25)
 671                      at25(this);
 672                  break;
 673              case GEVENT_TYPE_MOUSE_2:
 674                  at29 = 0;
 675                  break;
 676              default:
 677                  break;
 678              }
 679          }
 680      }
 681  }
 682  
 683  void ScrollLineUp(Widget* widget)
 684  {
 685      ((ScrollBar*)widget->at18)->ScrollRelative(-1);
 686  }
 687  
 688  void ScrollLineDown(Widget* widget)
 689  {
 690      ((ScrollBar*)widget->at18)->ScrollRelative(1);
 691  }
 692  
 693  ScrollBar::ScrollBar(int a1, int a2, int a3, int a4, int a5, int a6) : Container(a1, a2, 13, a3)
 694  {
 695      at52 = a4;
 696      at56 = a5;
 697      at6e = a6;
 698  
 699      at5e = new ScrollButton(1, 1, 11, 10, gGuiRes.Lookup("UPARROW", "QBM"), ScrollLineUp);
 700      at62 = new ScrollButton(1, a3-11, 11, 10, gGuiRes.Lookup("DNARROW", "QBM"), ScrollLineDown);
 701      at6a = new ThumbButton(1, 10, 11, 20);
 702  
 703      Insert(at5e);
 704      Insert(at62);
 705      Insert(at6a);
 706  
 707      at5a = 0;
 708  }
 709  
 710  void ScrollBar::ScrollRelative(int a1)
 711  {
 712      at6a->at4 = ClipRange(at6a->at4 + a1, 10, atc - 10 - at6a->atc);
 713  }
 714  
 715  void ScrollBar::Paint(int x, int y, char a1)
 716  {
 717      DrawBevel(x, y, x + at8, y + atc, gStdColor[24], gStdColor[16]);
 718      DrawRect(x + 1, y + 1, x + at8 - 1, y + atc - 1, gStdColor[0]);
 719      gColor = gStdColor[24];
 720      gfxFillBox(x + 2, y + 2, x + at8 - 2, y + atc - 2);
 721  
 722      Container::Paint(x, y, a1);
 723  }
 724  
 725  int MouseX, MouseY, MousedX, MousedY;
 726  
 727  GEVENT_TYPE GetEvent(GEVENT* event)
 728  {
 729      memset(event, 0, sizeof(GEVENT));
 730  
 731      char key = keyGetScan();
 732      if (key)
 733      {
 734          if (keystatus[sc_LeftShift])
 735              event->at6.keyboard.at2.bits.at3 = 1;
 736          if (keystatus[sc_RightShift])
 737              event->at6.keyboard.at2.bits.at4 = 1;
 738          event->at6.keyboard.at2.bits.at0 = event->at6.keyboard.at2.bits.at3 | event->at6.keyboard.at2.bits.at4;
 739          if (keystatus[sc_LeftControl])
 740              event->at6.keyboard.at2.bits.at5 = 1;
 741          if (keystatus[sc_RightShift])
 742              event->at6.keyboard.at2.bits.at6 = 1;
 743          event->at6.keyboard.at2.bits.at1 = event->at6.keyboard.at2.bits.at5 | event->at6.keyboard.at2.bits.at6;
 744          if (keystatus[sc_LeftAlt])
 745              event->at6.keyboard.at2.bits.at7 = 1;
 746          if (keystatus[sc_RightAlt])
 747              event->at6.keyboard.at2.bits.at8 = 1;
 748          event->at6.keyboard.at2.bits.at2 = event->at6.keyboard.at2.bits.at7 | event->at6.keyboard.at2.bits.at8;
 749          if (event->at6.keyboard.at2.bits.at2)
 750              event->at6.keyboard.at0 = 0;
 751          else if (event->at6.keyboard.at2.bits.at1)
 752              event->at6.keyboard.at0 = 0;
 753          else if (event->at6.keyboard.at2.bits.at0)
 754              event->at6.keyboard.at0 = key < 128 ? g_keyAsciiTableShift[key] : 0;
 755          else
 756              event->at6.keyboard.at0 = key < 128 ? g_keyAsciiTable[key] : 0;
 757          event->at0 = GEVENT_TYPE_KEYBOARD;
 758          event->at6.keyboard.at1 = key;
 759          if (key == sc_Escape)
 760              keystatus[sc_Escape] = 0;
 761          return event->at0;
 762      }
 763  
 764      event->at6.mouse.at10 = MousedX;
 765      event->at6.mouse.at14 = MousedY;
 766      event->at6.mouse.at8 = MouseX;
 767      event->at6.mouse.atc = MouseY;
 768  
 769      static int oldbuttons;
 770      static ClockTicks clickTime[5], downTime[5];
 771      int buttons = mouseReadButtons();
 772  
 773      int delta = buttons & ~oldbuttons;
 774  
 775      for (int i = 0, j = 1; i < 5; i++, j <<= 1)
 776      {
 777          event->at6.mouse.at4 = i;
 778          if (delta & j)
 779          {
 780              oldbuttons |= j;
 781              event->at0 = GEVENT_TYPE_MOUSE_1;
 782              if (clickTime[i]+60 < gFrameClock)
 783                  event->at6.mouse.at18 = 1;
 784              clickTime[i] = gFrameClock;
 785              downTime[i] = 0;
 786              return event->at0;
 787          }
 788          else if (oldbuttons & j)
 789          {
 790              if (buttons & j)
 791              {
 792                  downTime[i] += gFrameTicks;
 793                  if (event->at6.mouse.at10 || event->at6.mouse.at14)
 794                  {
 795                      event->at0 = GEVENT_TYPE_MOUSE_8;
 796                      return event->at0;
 797                  }
 798                  else if (downTime[i] > 60)
 799                  {
 800                      downTime[i] -= 6;
 801                      event->at0 = GEVENT_TYPE_MOUSE_4;
 802                      return event->at0;
 803                  }
 804              }
 805              else
 806              {
 807                  oldbuttons &= ~j;
 808                  event->at0 = GEVENT_TYPE_MOUSE_2;
 809                  return event->at0;
 810              }
 811          }
 812      }
 813      return GEVENT_TYPE_NONE;
 814  }
 815  
 816  MODAL_RESULT ShowModal(Container* container)
 817  {
 818      Container screen(0, 0, xdim, ydim);
 819  
 820      screen.Insert(container);
 821  
 822      container->at0 = (xdim - container->at8) / 2;
 823      container->at4 = (ydim - container->atc) / 2;
 824  
 825      int vc = xdim * ydim;
 826  
 827      while (!screen.SetFocus(1)) {}
 828  
 829      DICTNODE* hMouseCursor = gGuiRes.Lookup("MOUSE1", "QBM");
 830      dassert(hMouseCursor != NULL);
 831      pMouseCursor = (QBITMAP*)gGuiRes.Lock(hMouseCursor);
 832  
 833      DICTNODE* hFont = gGuiRes.Lookup("FONT1", "QFN");
 834      dassert(hFont != NULL);
 835      pFont = (QFONT*)gGuiRes.Lock(hFont);
 836  
 837      char* pFrameBackup = NULL;
 838  
 839      if (videoGetRenderMode() == REND_CLASSIC)
 840      {
 841          pFrameBackup = (char*)Xmalloc(vc);
 842          videoBeginDrawing();
 843          memcpy(pFrameBackup, (void*)frameplace, vc);
 844          videoEndDrawing();
 845      }
 846  
 847      MouseX = scale(g_mouseAbs.x, xdim, xres);
 848      MouseY = scale(g_mouseAbs.y, ydim, yres);
 849  
 850      container->at24 = 1;
 851      while (container->at24)
 852      {
 853          gFrameTicks = totalclock - gFrameClock;
 854          gFrameClock += gFrameTicks;
 855          UpdateBlinkClock((int)gFrameTicks);
 856          gameHandleEvents();
 857          MUSIC_Update();
 858  
 859          int nMouseX, nMouseY;
 860  
 861          nMouseX = scale(g_mouseAbs.x, xdim, xres);
 862          nMouseY = scale(g_mouseAbs.y, ydim, yres);
 863  
 864          MousedX = nMouseX - MouseX;
 865          MousedY = nMouseY - MouseY;
 866  
 867          MouseX = nMouseX;
 868          MouseY = nMouseY;
 869  
 870          GEVENT event;
 871          GetEvent(&event);
 872          if (event.at0 == GEVENT_TYPE_KEYBOARD)
 873          {
 874              switch (event.at6.keyboard.at1)
 875              {
 876              case sc_Escape:
 877                  container->EndModal(MODAL_RESULT_2);
 878                  continue;
 879              case sc_Return:
 880                  container->EndModal(MODAL_RESULT_1);
 881                  continue;
 882              case sc_Tab:
 883                  if (event.at6.keyboard.at2.bits.at0)
 884                  {
 885                      while (!screen.SetFocus(-1)) {}
 886                  }
 887                  else
 888                  {
 889                      while (!screen.SetFocus(1)) {}
 890                  }
 891                  continue;
 892              }
 893          }
 894          screen.HandleEvent(&event);
 895          if (videoGetRenderMode() == REND_CLASSIC)
 896          {
 897              videoBeginDrawing();
 898              memcpy((void*)frameplace, pFrameBackup, vc);
 899              videoEndDrawing();
 900          }
 901          screen.Paint(0, 0, 0);
 902          DrawMouseCursor(MouseX, MouseY);
 903          scrNextPage();
 904      }
 905  
 906      if (videoGetRenderMode() == REND_CLASSIC)
 907      {
 908          videoBeginDrawing();
 909          memcpy((void*)frameplace, pFrameBackup, vc);
 910          videoEndDrawing();
 911      }
 912      scrNextPage();
 913  
 914      gGuiRes.Unlock(hMouseCursor);
 915      pMouseCursor = NULL;
 916  
 917      gGuiRes.Unlock(hFont);
 918      pFont = NULL;
 919  
 920      Xfree(pFrameBackup);
 921  
 922      screen.Remove(container);
 923  
 924      return container->at25;
 925  }
 926  
 927  int GetNumberBox(const char* a1, int a2, int a3)
 928  {
 929      Win window(0, 0, 168, 40, a1);
 930      EditNumber* editnumber = new EditNumber(4, 4, 154, 16, a2);
 931  
 932      window.at5e->Insert(editnumber);
 933  
 934      ShowModal(&window);
 935  
 936      if (window.at25 != MODAL_RESULT_1)
 937          return a3;
 938  
 939      return editnumber->at130;
 940  }
 941  
 942  void Label::HandleEvent(GEVENT*)
 943  {
 944  }
 945  
 946  void HeadWidget::HandleEvent(GEVENT*)
 947  {
 948  }
 949  
 950  void HeadWidget::Paint(int, int, char)
 951  {
 952  }
 953  
 954  HeadWidget::HeadWidget(void) : Widget(0, 0, 0, 0)
 955  {
 956  }
 957  
 958  void Widget::EndModal(MODAL_RESULT a1)
 959  {
 960      at18->EndModal(a1);
 961  }
 962  
 963  Widget::~Widget()
 964  {
 965  }
 966  
 967  Widget::Widget(int a1, int a2, int a3, int a4)
 968  {
 969      at1c = 0;
 970      at1d = 0;
 971      at1e = 0;
 972      at1f = 0;
 973  
 974      at0 = a1;
 975      at4 = a2;
 976      at8 = a3;
 977      atc = a4;
 978  
 979      at10 = NULL;
 980      at14 = NULL;
 981      at18 = NULL;
 982  }
 983  
 984  Panel::Panel(int a1, int a2, int a3, int a4, int a5, int a6, int a7) : Container(a1, a2, a3, a4)
 985  {
 986      at52 = a5;
 987      at56 = a6;
 988      at5a = a7;
 989      at1c = 0;
 990  }
 991  
 992  BitButton::BitButton(int a1, int a2, int a3, int a4, DICTNODE* _bitmap, void(*a6)(Widget*)) : Button(a1, a2, a3, a4, a6)
 993  {
 994      bitmap = _bitmap;
 995  }
 996  
 997  ThumbButton::ThumbButton(int a1, int a2, int a3, int a4) : Button(a1, a2, a3, a4, MODAL_RESULT_0)
 998  {
 999  }
1000  
1001  ScrollButton::ScrollButton(int a1, int a2, int a3, int a4, DICTNODE* _bitmap, void(*a6)(Widget*)) : BitButton(a1, a2, a3, a4, _bitmap, a6)
1002  {
1003  }