GUI.CPP 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <conio.h>
  4. #include <helix.h>
  5. #include <ctype.h>
  6. #include "typedefs.h"
  7. #include "bstub.h"
  8. #include "gfx.h"
  9. #include "key.h"
  10. #include "misc.h"
  11. #include "gameutil.h"
  12. #include "debug4g.h"
  13. #include "resource.h"
  14. #include "globals.h"
  15. #include "gui.h"
  16. #include "screen.h"
  17. #include "mouse.h"
  18. #include "globals.h"
  19. #include <memcheck.h>
  20. #define kColorBackground gStdColor[20]
  21. #define kColorHighlight gStdColor[16]
  22. #define kColorShadow gStdColor[24]
  23. #define kBlinkTicks 100
  24. #define kBlinkOnTicks 60
  25. static int blinkClock = 0;
  26. Resource gGuiRes;
  27. static QBITMAP *pMouseCursor = NULL;
  28. static QFONT *pFont;
  29. void SetBlinkOn( void )
  30. {
  31. blinkClock = 0;
  32. }
  33. void SetBlinkOff( void )
  34. {
  35. blinkClock = kBlinkOnTicks;
  36. }
  37. BOOL IsBlinkOn( void )
  38. {
  39. return blinkClock < kBlinkOnTicks;
  40. }
  41. void UpdateBlinkClock( int ticks )
  42. {
  43. blinkClock += ticks;
  44. while (blinkClock >= kBlinkTicks)
  45. blinkClock -= kBlinkTicks;
  46. }
  47. static void CenterLabel(int x, int y, char *s, int foreColor)
  48. {
  49. if ( pFont != NULL )
  50. y -= pFont->height / 2;
  51. gfxDrawLabel(x - gfxGetLabelLen(s, pFont) / 2, y, foreColor, s, pFont);
  52. }
  53. void DrawBevel( int x0, int y0, int x1, int y1, int color1, int color2 )
  54. {
  55. Video.SetColor(color1);
  56. gfxHLine(y0, x0, x1 - 2);
  57. gfxVLine(x0, y0 + 1, y1 - 2);
  58. Video.SetColor(color2);
  59. gfxHLine(y1 - 1, x0 + 1, x1 - 1);
  60. gfxVLine(x1 - 1, y0 + 1, y1 - 2);
  61. }
  62. void DrawRect( int x0, int y0, int x1, int y1, int color )
  63. {
  64. Video.SetColor(color);
  65. gfxHLine(y0, x0, x1 - 1);
  66. gfxHLine(y1 - 1, x0, x1 - 1);
  67. gfxVLine(x0, y0 + 1, y1 - 2);
  68. gfxVLine(x1 - 1, y0 + 1, y1 - 2);
  69. }
  70. void DrawButtonFace( int x0, int y0, int x1, int y1, BOOL pressed )
  71. {
  72. Video.SetColor(kColorBackground);
  73. gfxFillBox(x0, y0, x1, y1);
  74. if (pressed)
  75. {
  76. Video.SetColor(gStdColor[26]);
  77. gfxHLine(y0, x0, x1 - 1);
  78. gfxVLine(x0, y0 + 1, y1 - 1);
  79. Video.SetColor(gStdColor[24]);
  80. gfxHLine(y0 + 1, x0 + 1, x1 - 1);
  81. gfxVLine(x0 + 1, y0 + 2, y1 - 1);
  82. DrawBevel(x0 + 2, y0 + 2, x1, y1, gStdColor[19], gStdColor[22]);
  83. }
  84. else
  85. {
  86. DrawBevel(x0, y0, x1, y1, gStdColor[16], gStdColor[24]);
  87. DrawBevel(x0 + 1, y0 + 1, x1 - 1, y1 - 1, gStdColor[18], gStdColor[22]);
  88. }
  89. }
  90. void DrawMouseCursor( int x, int y )
  91. {
  92. dassert(pMouseCursor != NULL);
  93. gfxDrawBitmap(pMouseCursor, x, y);
  94. }
  95. char GetHotKey( char *string )
  96. {
  97. for ( char *p = string; *p; p++ )
  98. {
  99. if ( *p == '&' )
  100. return (char)toupper(p[1]);
  101. }
  102. return '\0';
  103. }
  104. Container::Container( int left, int top, int width, int height) : Widget(left, top, width, height)
  105. {
  106. head.next = &head;
  107. head.prev = &head;
  108. focus = &head;
  109. isContainer = TRUE;
  110. isModal = FALSE;
  111. endState = mrNone;
  112. }
  113. virtual Container::~Container()
  114. {
  115. for (Widget *w = head.next; w != &head; w = head.next)
  116. {
  117. Remove(w);
  118. delete w;
  119. }
  120. }
  121. BOOL Container::SetFocus( int dir )
  122. {
  123. do
  124. {
  125. if (focus->isContainer)
  126. {
  127. if ( ((Container *)focus)->SetFocus(dir) )
  128. return TRUE;
  129. }
  130. if (dir > 0)
  131. focus = focus->next;
  132. else
  133. focus = focus->prev;
  134. if (focus == &head)
  135. return FALSE;
  136. } while (!focus->canFocus);
  137. return TRUE;
  138. }
  139. void Container::Insert( Widget *widget )
  140. {
  141. dassert(widget != NULL);
  142. widget->prev = head.prev;
  143. widget->next = &head;
  144. widget->prev->next = widget;
  145. widget->next->prev = widget;
  146. widget->owner = this;
  147. }
  148. void Container::Remove( Widget *widget )
  149. {
  150. dassert(widget != NULL);
  151. widget->prev->next = widget->next;
  152. widget->next->prev = widget->prev;
  153. }
  154. virtual void Container::Paint( int x, int y, BOOL /* hasFocus */ )
  155. {
  156. for ( Widget *w = head.next; w != &head; w = w->next)
  157. {
  158. w->Paint(x + w->left, y + w->top, w == focus);
  159. }
  160. }
  161. virtual void Container::HandleEvent( GEVENT *event )
  162. {
  163. if ( event->type & evMouse )
  164. {
  165. // make event relative to this container
  166. event->mouse.x -= left;
  167. event->mouse.y -= top;
  168. // find child owning location
  169. if ( event->type == evMouseDown )
  170. {
  171. drag = NULL;
  172. // iterate in reverse order since widgets on top have priority
  173. for ( Widget *w = head.prev; w != &head; w = w->prev)
  174. {
  175. if ( w->Contains(event->mouse.x, event->mouse.y) )
  176. {
  177. drag = w;
  178. if (drag->canFocus)
  179. focus = w;
  180. break;
  181. }
  182. }
  183. }
  184. if (drag != NULL)
  185. drag->HandleEvent(event);
  186. }
  187. else if ( event->type == evKeyDown )
  188. {
  189. focus->HandleEvent(event);
  190. // if key event not handled by focus, then broadcast to all childen
  191. if ( event->type != evNone )
  192. {
  193. for ( Widget *w = head.prev; w != &head; w = w->prev)
  194. {
  195. w->HandleEvent(event);
  196. if ( event->type == evNone )
  197. break;
  198. }
  199. }
  200. }
  201. }
  202. virtual void Container::EndModal( MODAL_RESULT result )
  203. {
  204. if ( isModal )
  205. {
  206. endState = result;
  207. isModal = FALSE;
  208. }
  209. else
  210. owner->EndModal(result);
  211. }
  212. virtual void Panel::Paint( int x, int y, BOOL hasFocus )
  213. {
  214. int i, n = 0;
  215. Video.SetColor(kColorBackground);
  216. gfxFillBox(x, y, x + width, y + height);
  217. for (i = qabs(size1); i > 0; n++, i--)
  218. {
  219. if (size1 > 0)
  220. DrawBevel(x + n, y + n, x + width - n, y + height - n, kColorHighlight, kColorShadow);
  221. else
  222. DrawBevel(x + n, y + n, x + width - n, y + height - n, kColorShadow, kColorHighlight);
  223. }
  224. n += size2;
  225. for (i = qabs(size3); i > 0; n++, i--)
  226. {
  227. if (size3 > 0)
  228. DrawBevel(x + n, y + n, x + width - n, y + height - n, kColorHighlight, kColorShadow);
  229. else
  230. DrawBevel(x + n, y + n, x + width - n, y + height - n, kColorShadow, kColorHighlight);
  231. }
  232. Container::Paint(x, y, hasFocus);
  233. }
  234. TitleBar::TitleBar( int left, int top, int width, int height, char *s ) : Widget(left, top, width, height)
  235. {
  236. strcpy(string, s);
  237. len = strlen(string);
  238. }
  239. virtual void TitleBar::Paint( int x, int y, BOOL /* hasFocus */ )
  240. {
  241. Video.SetColor(gStdColor[1]);
  242. gfxFillBox(x, y, x + width, y + height);
  243. DrawBevel(x, y, x + width, y + height, gStdColor[9], gStdColor[30]);
  244. CenterLabel(x + width / 2, y + height / 2, string, gStdColor[15]);
  245. }
  246. virtual void TitleBar::HandleEvent( GEVENT *event )
  247. {
  248. if ( event->type & evMouse && event->mouse.button == 0 )
  249. {
  250. switch (event->type)
  251. {
  252. case evMouseDrag:
  253. owner->left += event->mouse.dx;
  254. owner->top += event->mouse.dy;
  255. event->Clear();
  256. break;
  257. case evMouseUp:
  258. break;
  259. }
  260. }
  261. }
  262. Window::Window( int left, int top, int width, int height, char *title) : Panel(left, top, width, height, 1, 1, -1)
  263. {
  264. titleBar = new TitleBar( 3, 3, width - 6, 12, title);
  265. client = new Container(3, 15, width - 6, height - 18);
  266. Container::Insert(titleBar);
  267. Container::Insert(client);
  268. drag = NULL;
  269. }
  270. virtual void Button::Paint( int x, int y, BOOL /* hasFocus */ )
  271. {
  272. Video.SetColor(gStdColor[0]);
  273. gfxHLine(y, x + 1, x + width - 2);
  274. gfxHLine(y + height - 1, x + 1, x + width - 2);
  275. gfxVLine(x, y + 1, y + height - 2);
  276. gfxVLine(x + width - 1, y + 1, y + height - 2);
  277. DrawButtonFace(x + 1, y + 1, x + width - 1, y + height - 1, pressed);
  278. }
  279. virtual void Button::HandleEvent( GEVENT *event )
  280. {
  281. if ( event->type == evKeyDown )
  282. {
  283. if ( event->key.ascii == ' ' )
  284. {
  285. pressed = !pressed;
  286. if (clickProc != NULL)
  287. clickProc(this);
  288. if ( result )
  289. EndModal(result);
  290. event->Clear();
  291. }
  292. }
  293. else if ( event->type & evMouse )
  294. {
  295. if (event->mouse.button != 0)
  296. return;
  297. switch (event->type)
  298. {
  299. case evMouseDown:
  300. pressed = TRUE;
  301. event->Clear();
  302. break;
  303. case evMouseDrag:
  304. pressed = Contains(event->mouse.x, event->mouse.y);
  305. event->Clear();
  306. break;
  307. case evMouseUp:
  308. pressed = FALSE;
  309. if ( Contains(event->mouse.x, event->mouse.y) )
  310. {
  311. if (clickProc != NULL)
  312. clickProc(this);
  313. if ( result )
  314. EndModal(result);
  315. }
  316. event->Clear();
  317. break;
  318. }
  319. }
  320. }
  321. virtual void TextButton::Paint( int x, int y, BOOL hasFocus )
  322. {
  323. Video.SetColor(gStdColor[0]);
  324. gfxHLine(y + 1, x + 2, x + width - 3);
  325. gfxHLine(y + height - 2, x + 2, x + width - 3);
  326. gfxVLine(x + 1, y + 2, y + height - 3);
  327. gfxVLine(x + width - 2, y + 2, y + height - 3);
  328. if (hasFocus)
  329. {
  330. Video.SetColor(gStdColor[15]);
  331. gfxHLine(y, x + 1, x + width - 2);
  332. gfxHLine(y + height - 1, x + 1, x + width - 2);
  333. gfxVLine(x, y + 1, y + height - 2);
  334. gfxVLine(x + width - 1, y + 1, y + height - 2);
  335. gfxPixel(x + 1, y + 1);
  336. gfxPixel(x + width - 2, y + 1);
  337. gfxPixel(x + 1, y + height - 2);
  338. gfxPixel(x + width - 2, y + height - 2);
  339. }
  340. DrawButtonFace(x + 2, y + 2, x + width - 2, y + height - 2, pressed);
  341. if ( pressed )
  342. CenterLabel(x + width / 2 + 1, y + height / 2 + 1, text, gStdColor[0]);
  343. else
  344. CenterLabel(x + width / 2, y + height / 2, text, gStdColor[0]);
  345. }
  346. virtual void TextButton::HandleEvent( GEVENT *event )
  347. {
  348. if ( event->type == evKeyDown )
  349. {
  350. if ( ScanToAsciiShifted[event->key.make] == GetHotKey(text) )
  351. {
  352. pressed = !pressed;
  353. if (clickProc != NULL)
  354. clickProc(this);
  355. if ( result )
  356. EndModal(result);
  357. event->Clear();
  358. }
  359. }
  360. Button::HandleEvent(event);
  361. }
  362. virtual void BitButton::Paint( int x, int y, BOOL /* hasFocus */ )
  363. {
  364. Video.SetColor(gStdColor[0]);
  365. gfxHLine(y, x + 1, x + width - 2);
  366. gfxHLine(y + height - 1, x + 1, x + width - 2);
  367. gfxVLine(x, y + 1, y + height - 2);
  368. gfxVLine(x + width - 1, y + 1, y + height - 2);
  369. DrawButtonFace(x + 1, y + 1, x + width - 1, y + height - 1, pressed);
  370. int cx = x + width / 2;
  371. int cy = y + height / 2;
  372. QBITMAP *pBitmap = (QBITMAP *)gGuiRes.Load(hBitmap);
  373. if ( pressed )
  374. gfxDrawBitmap(pBitmap, cx - pBitmap->cols / 2 + 1, cy - pBitmap->rows / 2 + 1);
  375. else
  376. gfxDrawBitmap(pBitmap, cx - pBitmap->cols / 2, cy - pBitmap->rows / 2);
  377. }
  378. EditText::EditText( int left, int top, int width, int height, char *s ) : Widget(left, top, width, height)
  379. {
  380. canFocus = TRUE;
  381. strcpy(string, s);
  382. len = strlen(string);
  383. pos = len;
  384. maxlen = width / 8 - 1;
  385. }
  386. virtual void EditText::Paint( int x, int y, BOOL hasFocus )
  387. {
  388. DrawBevel(x, y, x + width - 1, y + height - 1, kColorShadow, kColorHighlight);
  389. DrawRect(x + 1, y + 1, x + width - 2, y + height - 2, gStdColor[0]);
  390. Video.SetColor(gStdColor[hasFocus ? 15 : 20]);
  391. gfxFillBox(x + 2, y + 2, x + width - 3, y + height - 3);
  392. gfxDrawText(x + 3, y + height / 2 - 4, gStdColor[0], string, pFont);
  393. if ( hasFocus && IsBlinkOn() )
  394. {
  395. Video.SetColor(gStdColor[0]);
  396. gfxVLine(x + gfxGetTextNLen(string, pFont, pos) + 3, y + height / 2 - 4, y + height / 2 + 3);
  397. }
  398. }
  399. virtual void EditText::HandleEvent( GEVENT *event )
  400. {
  401. if ( event->type & evMouse )
  402. {
  403. if (event->mouse.button != 0)
  404. return;
  405. switch (event->type)
  406. {
  407. case evMouseDown:
  408. case evMouseDrag:
  409. pos = gfxFindTextPos(string, pFont, event->mouse.x - left);
  410. SetBlinkOn();
  411. event->Clear();
  412. break;
  413. }
  414. }
  415. else if ( event->type == evKeyDown )
  416. {
  417. switch ( event->key.make )
  418. {
  419. case KEY_BACKSPACE:
  420. if (pos > 0)
  421. {
  422. memmove(&string[pos - 1], &string[pos], len - pos);
  423. pos--;
  424. len--;
  425. string[len] = '\0';
  426. }
  427. event->Clear();
  428. break;
  429. case KEY_DELETE:
  430. if (pos < len)
  431. {
  432. len--;
  433. memmove(&string[pos], &string[pos + 1], len - pos);
  434. string[len] = '\0';
  435. }
  436. event->Clear();
  437. break;
  438. case KEY_LEFT:
  439. if (pos > 0)
  440. pos--;
  441. event->Clear();
  442. break;
  443. case KEY_RIGHT:
  444. if (pos < len)
  445. pos++;
  446. event->Clear();
  447. break;
  448. case KEY_HOME:
  449. pos = 0;
  450. event->Clear();
  451. break;
  452. case KEY_END:
  453. pos = len;
  454. event->Clear();
  455. break;
  456. default:
  457. if ( event->key.ascii != 0 )
  458. {
  459. if ( len < maxlen )
  460. {
  461. memmove(&string[pos+1], &string[pos], len - pos);
  462. string[pos++] = event->key.ascii;
  463. string[++len] = '\0';
  464. }
  465. event->Clear();
  466. }
  467. break;
  468. }
  469. SetBlinkOn();
  470. }
  471. }
  472. EditNumber::EditNumber( int left, int top, int width, int height, int n ) : EditText( left, top, width, height, "")
  473. {
  474. value = n;
  475. itoa(n, string, 10);
  476. len = strlen(string);
  477. pos = len;
  478. }
  479. virtual void EditNumber::HandleEvent( GEVENT *event )
  480. {
  481. if ( event->type == evKeyDown )
  482. {
  483. switch ( event->key.make )
  484. {
  485. case KEY_BACKSPACE:
  486. case KEY_DELETE:
  487. case KEY_LEFT:
  488. case KEY_RIGHT:
  489. case KEY_HOME:
  490. case KEY_END:
  491. break;
  492. case KEY_MINUS:
  493. if (pos == 0 && string[0] != '-' && len < maxlen)
  494. {
  495. memmove(&string[1], &string[0], len);
  496. string[pos++] = '-';
  497. string[++len] = '\0';
  498. }
  499. event->Clear();
  500. break;
  501. default:
  502. if ( event->key.ascii != 0 )
  503. {
  504. if (event->key.ascii >= '0' && event->key.ascii <= '9' && len < maxlen)
  505. {
  506. memmove(&string[pos+1], &string[pos], len - pos);
  507. string[pos++] = event->key.ascii;
  508. string[++len] = '\0';
  509. }
  510. event->Clear();
  511. }
  512. break;
  513. }
  514. }
  515. EditText::HandleEvent( event );
  516. value = atoi(string);
  517. }
  518. virtual void ThumbButton::HandleEvent( GEVENT *event )
  519. {
  520. if ( event->type & evMouse )
  521. {
  522. if (event->mouse.button != 0)
  523. return;
  524. switch (event->type)
  525. {
  526. case evMouseDrag:
  527. top = ClipRange(event->mouse.y - height / 2, kSBHeight, owner->height - kSBHeight - height);
  528. break;
  529. case evMouseDown:
  530. pressed = TRUE;
  531. break;
  532. case evMouseUp:
  533. pressed = FALSE;
  534. break;
  535. }
  536. }
  537. }
  538. virtual void ScrollButton::HandleEvent( GEVENT *event )
  539. {
  540. if ( event->type & evMouse )
  541. {
  542. if (event->mouse.button != 0)
  543. return;
  544. switch (event->type)
  545. {
  546. case evMouseDown:
  547. pressed = TRUE;
  548. if (clickProc != NULL)
  549. clickProc(this);
  550. break;
  551. case evMouseDrag:
  552. pressed = Contains(event->mouse.x, event->mouse.y);
  553. break;
  554. case evMouseRepeat:
  555. if ( pressed && clickProc != NULL )
  556. clickProc(this);
  557. break;
  558. case evMouseUp:
  559. pressed = FALSE;
  560. break;
  561. }
  562. }
  563. }
  564. void ScrollLineUp( Widget *widget )
  565. {
  566. ScrollBar *pScrollBar = (ScrollBar *)widget->owner;
  567. pScrollBar->ScrollRelative(-1);
  568. }
  569. void ScrollLineDown( Widget *widget )
  570. {
  571. ScrollBar *pScrollBar = (ScrollBar *)widget->owner;
  572. pScrollBar->ScrollRelative(+1);
  573. }
  574. ScrollBar::ScrollBar( int left, int top, int height, int min, int max, int value ) :
  575. Container(left, top, kSBWidth + 2, height), min(min), max(max), value(value)
  576. {
  577. pbUp = new ScrollButton(1, 1, gGuiRes.Lookup("UPARROW", ".QBM"), ScrollLineUp);
  578. pbDown = new ScrollButton(1, height - kSBHeight - 1, gGuiRes.Lookup("DNARROW", ".QBM"), ScrollLineDown);
  579. // pcThumbBar = new Container(1,
  580. pbThumb = new ThumbButton(1, 10, 20);
  581. Insert(pbUp);
  582. Insert(pbDown);
  583. Insert(pbThumb);
  584. size = 0;
  585. }
  586. void ScrollBar::ScrollRelative( int offset )
  587. {
  588. pbThumb->top = ClipRange(pbThumb->top + offset, kSBHeight, height - kSBHeight - pbThumb->height);
  589. }
  590. virtual void ScrollBar::Paint( int x, int y, BOOL hasFocus )
  591. {
  592. DrawBevel(x, y, x + width, y + height, kColorShadow, kColorHighlight);
  593. DrawRect(x + 1, y + 1, x + width - 1, y + height - 1, gStdColor[0]);
  594. Video.SetColor(kColorShadow);
  595. gfxFillBox(x + 2, y + 2, x + width - 2, y + height - 2);
  596. Container::Paint(x, y, hasFocus);
  597. }
  598. #define kRepeatDelay 60
  599. #define kRepeatInterval 6
  600. #define kDoubleClick 60
  601. GEVENT_TYPE GetEvent( GEVENT *event )
  602. {
  603. static int clickTime[3], downTime[3];
  604. static BYTE oldbuttons = 0;
  605. BYTE newbuttons;
  606. BYTE key;
  607. memset(event, 0, sizeof(GEVENT));
  608. if ( (key = keyGet()) != 0 )
  609. {
  610. if ( keystatus[KEY_LSHIFT] )
  611. event->key.lshift = 1;
  612. if ( keystatus[KEY_RSHIFT] )
  613. event->key.rshift = 1;
  614. event->key.shift = event->key.lshift | event->key.rshift;
  615. if ( keystatus[KEY_LCTRL] )
  616. event->key.lcontrol = 1;
  617. if ( keystatus[KEY_RCTRL] )
  618. event->key.rcontrol = 1;
  619. event->key.control = event->key.lcontrol | event->key.rcontrol;
  620. if ( keystatus[KEY_LALT] )
  621. event->key.lalt = 1;
  622. if ( keystatus[KEY_RALT] )
  623. event->key.ralt = 1;
  624. event->key.alt = event->key.lalt | event->key.ralt;
  625. if ( event->key.alt )
  626. event->key.ascii = 0;
  627. else if ( event->key.control )
  628. event->key.ascii = 0;
  629. else if ( event->key.shift )
  630. event->key.ascii = ScanToAsciiShifted[key];
  631. else
  632. event->key.ascii = ScanToAscii[key];
  633. event->key.make = key;
  634. event->type = evKeyDown;
  635. if ( key == KEY_ESC )
  636. keystatus[KEY_ESC] = 0; // some of Ken's stuff still checks this!
  637. return event->type;
  638. }
  639. event->mouse.dx = Mouse::dX;
  640. event->mouse.dy = Mouse::dY;
  641. event->mouse.x = Mouse::X;
  642. event->mouse.y = Mouse::Y;
  643. // which buttons just got pressed?
  644. newbuttons = (BYTE)(~oldbuttons & Mouse::buttons);
  645. BYTE buttonMask = 1;
  646. for (int nButton = 0; nButton < 3; nButton++, buttonMask <<= 1)
  647. {
  648. event->mouse.button = nButton;
  649. if (newbuttons & buttonMask)
  650. {
  651. oldbuttons |= buttonMask;
  652. event->type = evMouseDown;
  653. // create double click event if in time interval
  654. if ( gFrameClock < clickTime[nButton] + kDoubleClick )
  655. event->mouse.doubleClick = TRUE;
  656. clickTime[nButton] = gFrameClock;
  657. downTime[nButton] = 0;
  658. return event->type;
  659. }
  660. else if (oldbuttons & buttonMask)
  661. {
  662. if (Mouse::buttons & buttonMask)
  663. {
  664. downTime[nButton] += gFrameTicks;
  665. if ( event->mouse.dx || event->mouse.dy )
  666. {
  667. event->type = evMouseDrag;
  668. return event->type;
  669. }
  670. if ( downTime[nButton] > kRepeatDelay )
  671. {
  672. downTime[nButton] -= kRepeatInterval;
  673. event->type = evMouseRepeat;
  674. return event->type;
  675. }
  676. }
  677. else
  678. {
  679. oldbuttons &= ~buttonMask;
  680. event->type = evMouseUp;
  681. return event->type;
  682. }
  683. }
  684. }
  685. return evNone;
  686. }
  687. MODAL_RESULT ShowModal( Container *dialog )
  688. {
  689. GEVENT event;
  690. Container desktop(0, 0, xdim, ydim);
  691. desktop.Insert(dialog);
  692. // center the dialog
  693. dialog->left = (xdim - dialog->width) / 2;
  694. dialog->top = (ydim - dialog->height) / 2;
  695. int saveSize = xdim * ydim;
  696. // find first item for focus
  697. while (!desktop.SetFocus(+1));
  698. BYTE *saveUnder = (BYTE *)Resource::Alloc(saveSize);
  699. RESHANDLE hMouseCursor = gGuiRes.Lookup("MOUSE1", ".QBM");
  700. dassert(hMouseCursor != NULL);
  701. pMouseCursor = (QBITMAP *)gGuiRes.Lock(hMouseCursor);
  702. RESHANDLE hFont = gGuiRes.Lookup("FONT1", ".QFN");
  703. dassert(hFont != NULL);
  704. pFont = (QFONT *)gGuiRes.Lock(hFont);
  705. // copy save under from last displayed page
  706. switch (vidoption)
  707. {
  708. case 0: // unchained mode
  709. break;
  710. case 1: // linear frame buffer mode
  711. case 2: // screen buffer mode
  712. memcpy(saveUnder, frameplace, saveSize);
  713. break;
  714. case 3: // tseng mode
  715. page = (page + 3) & 3;
  716. outp(0x3CD, page + (page << 4));
  717. memcpy(saveUnder, frameplace, saveSize);
  718. page = (page + 1) & 3;
  719. outp(0x3CD, page + (page << 4));
  720. break;
  721. case 4: // paradise
  722. page = (page + 3) & 3;
  723. outp(0x3CE, 0x09); outp(0x3CF, page << 4);
  724. memcpy(saveUnder, frameplace, saveSize);
  725. page = (page + 1) & 3;
  726. outp(0x3CE, 0x09); outp(0x3CF, page << 4);
  727. break;
  728. case 5: // s3
  729. page = (page + 3) & 3;
  730. outp(0x3D4, 0x35); outp(0x3D5, page);
  731. memcpy(saveUnder, frameplace, saveSize);
  732. page = (page + 1) & 3;
  733. outp(0x3D4, 0x35); outp(0x3D5, page);
  734. break;
  735. }
  736. dialog->isModal = TRUE;
  737. while ( dialog->isModal )
  738. {
  739. gFrameTicks = gGameClock - gFrameClock;
  740. gFrameClock += gFrameTicks;
  741. UpdateBlinkClock(gFrameTicks);
  742. Mouse::Read(gFrameTicks);
  743. GetEvent(&event) ;
  744. // trap certain dialog keys
  745. if ( event.type == evKeyDown )
  746. {
  747. switch ( event.key.ascii )
  748. {
  749. case 27:
  750. dialog->EndModal(mrCancel);
  751. continue;
  752. case 13:
  753. dialog->EndModal(mrOk);
  754. continue;
  755. case 9:
  756. if ( event.key.shift )
  757. while (!desktop.SetFocus(-1));
  758. else
  759. while (!desktop.SetFocus(+1));
  760. continue;
  761. }
  762. }
  763. desktop.HandleEvent(&event);
  764. // copy the save under first
  765. memcpy(frameplace, saveUnder, saveSize);
  766. desktop.Paint(0, 0, FALSE);
  767. DrawMouseCursor(Mouse::X, Mouse::Y);
  768. if (vidoption == 2)
  769. WaitVSync();
  770. scrNextPage();
  771. // restore the save under after page flipping
  772. memcpy(frameplace, saveUnder, saveSize);
  773. }
  774. memcpy(frameplace, saveUnder, saveSize);
  775. scrNextPage();
  776. gGuiRes.Unlock(hMouseCursor);
  777. pMouseCursor = NULL;
  778. gGuiRes.Unlock(hFont);
  779. pFont = NULL;
  780. Resource::Free(saveUnder);
  781. desktop.Remove(dialog);
  782. return dialog->endState;
  783. }
  784. int GetStringBox( char *title, char *s )
  785. {
  786. // create the dialog
  787. Window dialog(0, 0, 168, 40, title);
  788. // this will automatically be destroyed when the dialog is destroyed
  789. EditText *el = new EditText(4, 4, 154, 16, s);
  790. dialog.Insert(el);
  791. ShowModal(&dialog);
  792. if ( dialog.endState != mrOk)
  793. return 0; // pressed escape
  794. // copy the edited string
  795. strcpy(s, el->string);
  796. return 1;
  797. }
  798. int GetNumberBox( char *title, int n, int nDefault )
  799. {
  800. // create the dialog
  801. Window dialog(0, 0, 168, 40, title);
  802. // this will automatically be destroyed when the dialog is destroyed
  803. EditNumber *en = new EditNumber(4, 4, 154, 16, n);
  804. dialog.Insert(en);
  805. ShowModal(&dialog);
  806. if ( dialog.endState != mrOk)
  807. return nDefault; // pressed escape
  808. return en->value;
  809. }