/* * InterfaceTab: User is moving focus from given control in given direction. * Return False iff event should not be sent to other modules (i.e. handled here) */ Bool InterfaceTab(int control, Bool forward) { switch (control) { case IDC_MAIN: if (!forward) break; if( StatsGetCurrentGroup() == STATS_INVENTORY ) // ajw InventorySetFocus( forward ); else StatsSetFocus( forward ); return False; case IDC_MAINTEXT: case IDC_TEXTINPUT: if (forward) break; if( StatsGetCurrentGroup() == STATS_INVENTORY ) // ajw InventorySetFocus( forward ); else StatsSetFocus( forward ); return False; } return True; }
/* * InventoryDisplayScrollbar: Determine whether a scrollbar is necessary, * and draw it if so. Also may involve moving the inventory box around. */ void InventoryDisplayScrollbar(void) { ShowWindow(hwndInvDialog, SW_HIDE); /* Hide scrollbar ugliness */ ShowWindow(hwndInvScroll, SW_HIDE); has_scrollbar = (num_items > rows * cols); InventoryComputeRowsCols(); MoveWindow(hwndInvDialog, inventory_area.x, inventory_area.y, inventory_area.cx, inventory_area.cy, FALSE); MoveWindow(hwndInv, 0, 0, inventory_area.cx - inventory_scrollbar_width, inventory_area.cy, FALSE); MoveWindow(hwndInvScroll, inventory_area.cx - inventory_scrollbar_width, 0, inventory_scrollbar_width, inventory_area.cy, TRUE); InventoryScrollRange(); if( StatsGetCurrentGroup() == STATS_INVENTORY ) // ajw { ShowWindow(hwndInvDialog, SW_SHOWNORMAL); ShowWindow(hwndInvScroll, has_scrollbar ? SW_SHOWNORMAL : SW_HIDE); } }
/* * StatsListDrawItem: Message handler for stats list boxes. Return TRUE iff * message is handled. */ BOOL StatsListDrawItem(HWND hwnd, const DRAWITEMSTRUCT *lpdis) { AREA stats_area; if (hList == NULL) return TRUE; switch (lpdis->itemAction) { case ODA_SELECT: case ODA_DRAWENTIRE: /* If box is empty, do nothing */ if (lpdis->itemID == -1) return TRUE; /* Draw window background at correct offset */ StatsGetArea(&stats_area); DrawWindowBackgroundColor(pinventory_bkgnd(), lpdis->hDC, (RECT *) (&lpdis->rcItem), // was NULL stats_area.x + lpdis->rcItem.left, stats_area.y + lpdis->rcItem.top + StatsGetButtonBorder(), -1); /* Draw info on stat */ StatsListDrawStat(lpdis, (Bool) (lpdis->itemState & ODS_SELECTED), (Bool)( StatsGetCurrentGroup() == STATS_SPELLS ) ); break; case ODA_FOCUS: // DrawFocusRect(lpdis->hDC, &lpdis->rcItem); break; } return TRUE; }
/* * StatsListDrawStat: Draw info about stat in stat list box. * selected is True iff the item is currently selected. */ void StatsListDrawStat(const DRAWITEMSTRUCT *lpdis, Bool selected, Bool bShowSpellIcon ) { HFONT hOldFont; Statistic *s; char str[MAXRSCSTRING + 10]; RECT r; int lastItem = ListBox_GetCount(lpdis->hwndItem) - 1; RECT rcWnd; GetClientRect(lpdis->hwndItem,&rcWnd); if (lpdis->rcItem.bottom > rcWnd.bottom) return; hOldFont = (HFONT) SelectObject(lpdis->hDC, GetFont(FONT_STATS)); s = (Statistic *) ListBox_GetItemData(hList, lpdis->itemID); if (s == NULL) return; sprintf(str, "%s %d%%", LookupNameRsc(s->name_res), s->list.value); SetBkMode(lpdis->hDC, TRANSPARENT); memcpy(&r, &lpdis->rcItem, sizeof(RECT)); r.left += ENCHANT_SIZE + 2; // Draw text with drop shadow SetTextColor(lpdis->hDC, GetColor(COLOR_STATSBGD)); //DrawText(lpdis->hDC, str, strlen(str), &r, DT_CENTER); DrawText( lpdis->hDC, str, strlen(str), &r, DT_LEFT ); OffsetRect(&r, 1, 1); SetTextColor(lpdis->hDC, selected ? GetColor(COLOR_HIGHLITE) : GetColor(COLOR_STATSFGD)); //DrawText(lpdis->hDC, str, strlen(str), &r, DT_CENTER); DrawText( lpdis->hDC, str, strlen(str), &r, DT_LEFT ); SelectObject(lpdis->hDC, hOldFont); switch (StatsGetCurrentGroup()) { AREA areaIcon; case STATS_SPELLS: case STATS_SKILLS: areaIcon.x = lpdis->rcItem.left; areaIcon.y = lpdis->rcItem.top; areaIcon.cx = ENCHANT_SIZE; //xxx areaIcon.cy = ENCHANT_SIZE; DrawObjectIcon(lpdis->hDC, s->list.icon, 0, True, &areaIcon, NULL, 0, 0, True); break; } if (lastItem == (int)lpdis->itemID) { RECT rcWnd; GetClientRect(lpdis->hwndItem,&rcWnd); rcWnd.top = lpdis->rcItem.bottom; if (rcWnd.top < rcWnd.bottom) InvalidateRect(lpdis->hwndItem,&rcWnd,TRUE); } }
/* * StatButtonDrawItem: Draw stat button for given DRAWITEMSTRUCT structure. */ Bool StatButtonDrawItem(HWND hwnd, const DRAWITEMSTRUCT *lpdis) { int group, xSrc; int xDest; StatButton *button; Bool bPressed = False; switch (lpdis->itemAction) { case ODA_SELECT: case ODA_DRAWENTIRE: // Draw bitmap, if button has one group = StatsFindGroupByHwnd(lpdis->hwndItem) - 1; if( group == GROUP_NONE || buttons[group].bitsLeft == NULL ) { FillRect(lpdis->hDC, &lpdis->rcItem, (HBRUSH) GetStockObject(LTGRAY_BRUSH)); } else { button = &buttons[group]; // Pick image to draw, depending on whether button is pressed if( lpdis->itemState & ODS_SELECTED || StatsGetCurrentGroup() == group + 2 ) bPressed = True; SelectPalette(lpdis->hDC, cinfo->hPal, FALSE); // OffscreenWindowBackground( NULL, button->x, button->y, button->width, button->height ); // Left piece. if( bPressed ) xSrc = button->iWidthLeft; else xSrc = 0; OffscreenBitBlt(lpdis->hDC, 0, 0, button->iWidthLeft, button->height, (BYTE *) button->bitsLeft, xSrc, 0, 2 * button->iWidthLeft, OBB_FLIP | OBB_COPY | OBB_TRANSPARENT ); // Middle repeating pieces. if( bPressed ) xSrc = button->iWidthMid; xDest = button->iWidthLeft; while( xDest < button->width - button->iWidthRight ) { OffscreenBitBlt(lpdis->hDC, xDest, 0, button->iWidthMid, button->height, (BYTE *) button->bitsMid, xSrc, 0, 2 * button->iWidthMid, OBB_FLIP | OBB_COPY | OBB_TRANSPARENT ); xDest += button->iWidthMid; } // Right piece. if( bPressed ) xSrc = button->iWidthRight; xDest = button->width - button->iWidthRight; OffscreenBitBlt(lpdis->hDC, xDest, 0, button->iWidthRight, button->height, (BYTE *) button->bitsRight, xSrc, 0, 2 * button->iWidthRight, OBB_FLIP | OBB_COPY | OBB_TRANSPARENT ); } return True; } return False; }
/* * StatButtonCommand: User pressed stat button */ void StatButtonCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) { int group; list_type stat_list; group = StatsFindGroupByHwnd(hwndCtl) + 1; // Skip main stat group if (group == GROUP_NONE) return; if (group != StatsGetCurrentGroup()) { // ajw Changes to make Inventory act somewhat like one of the stats groups. if( StatsGetCurrentGroup() == STATS_INVENTORY ) { // Inventory must be going away. ShowInventory( False ); // StatsShowGroup( True ); } if( group == STATS_INVENTORY ) { // The hacks continue... Force previously toggled non-inventory button to repaint and show new unpressed state. InvalidateRect( buttons[ StatsGetCurrentGroup()-2 ].hwnd, NULL, FALSE ); StatsShowGroup( False ); ShowInventory( True ); DisplayInventoryAsStatGroup( (BYTE)STATS_INVENTORY ); } else { // Check stat cache; if group not present, ask server if (StatCacheGetEntry(group, &stat_list) == True) DisplayStatGroup((BYTE) group, stat_list); else { debug(("Requesting group %d\n", group)); RequestStats(group); } } } if( StatsGetCurrentGroup() == STATS_INVENTORY ) InventorySetFocus( True ); // Force focus to leave stats group window after button within it was pushed. // [ xxx Still broken - click on Inv when it is already selected, but drag off of button and release. ] }
/* * StatsListLButtonDblClk: User double-clicked left button on stats list. ajw */ void StatsListLButtonDblClk(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags) { char pszLabel[256]; char pszCommand[256]; int iLabelLen; int index = y / ListBox_GetItemHeight(hwnd, 0) + ListBox_GetTopIndex(hwnd); if (index >= ListBox_GetCount(hwnd)) return; if ((GetPlayerInfo()->viewID != 0) && (GetPlayerInfo()->viewID != GetPlayerInfo()->id)) { if (!(GetPlayerInfo()->viewFlags & REMOTE_VIEW_CAST)) return; } ListBox_SetCurSel(hwnd, index); iLabelLen = ListBox_GetTextLen( hwnd, index ); if( ListBox_GetText( hwnd, index, pszLabel ) != LB_ERR ) { if( StatsGetCurrentGroup() == STATS_SPELLS ) { strcpy( pszCommand, "zaubern " ); } else if (StatsGetCurrentGroup() == STATS_SKILLS) { strcpy( pszCommand, "perform " ); return; // not implimented yet } else { return; // not going to do anything for non skills/stats } strcat( pszCommand, pszLabel ); PerformAction( A_GOTOMAIN, NULL ); // For targeting icon to appear, focus must be on main view window. PerformAction( A_TEXTCOMMAND, pszCommand ); } }
/* * InterfaceRedrawModule: Called when main window needs to be redrawn. */ void InterfaceRedrawModule(HDC hdc) { UserAreaRedraw(); InterfaceDrawElements(hdc); StatsDrawBorder(); StatsMainRedraw(); StatsDraw(); if( StatsGetCurrentGroup() == STATS_INVENTORY ) { InvalidateRect( GetHwndInv(), NULL, FALSE ); ShowInventory(TRUE); InventoryRedraw(); } }
/* * StatsListResize: Called when main window resized. */ void StatsListResize(list_type stats) { AREA stats_area; int y; StatsGetArea(&stats_area); y = StatsGetButtonBorder(); MoveWindow(hList, 0, y, stats_area.cx, stats_area.cy - y, TRUE); // Hide scrollbar if not needed num_visible = (stats_area.cy - y) / max(ListBox_GetItemHeight(hList, 0), 1); if (num_visible >= ListBox_GetCount(hList)) SetScrollRange(hList, SB_VERT, 0, 0, TRUE); else { SetScrollRange(hList, SB_VERT, 0, ListBox_GetCount(hList) - num_visible, TRUE); SetScrollPos(hList, SB_VERT, ListBox_GetTopIndex(hList), TRUE); } if( StatsGetCurrentGroup() != STATS_INVENTORY ) // ajw ShowWindow(hList, SW_NORMAL); }
/* * StatsNumResize: Called when main window resized. */ void StatsNumResize(list_type stats) { int x, y, height, count, num_stats; list_type l; AREA stats_area; Bool has_scrollbar = False; StatsGetArea(&stats_area); // First, see how many stats will fit y = StatsGetButtonBorder(); num_visible = 0; num_stats = 0; for (l = stats; l != NULL; l = l->next) { Statistic *s = (Statistic *) (l->data); if (s->numeric.tag != STAT_INT) continue; num_stats++; if (y + s->cy <= stats_area.cy) { y += s->cy; num_visible++; } } if (num_visible < num_stats) has_scrollbar = True; top_stat = min(top_stat, num_stats - num_visible); // Move graph bars x = stats_area.cx / 2; stats_bar_width = has_scrollbar ? stats_area.cx / 2 - stats_scrollbar_width - 1 : stats_area.cx / 2; stats_bar_width -= RIGHT_BORDER; num_visible = 0; count = 0; y = StatsGetButtonBorder(); for (l = stats; l != NULL; l = l->next) { Statistic *s = (Statistic *) (l->data); if (s->numeric.tag != STAT_INT) continue; // Take into account position of scrollbar if (count++ < top_stat) { ShowWindow(s->hControl, SW_HIDE); continue; } // Center bar vertically s->y = y; y += s->cy; MoveWindow(s->hControl, x, s->y + (s->cy - STATS_BAR_HEIGHT) / 2, stats_bar_width, STATS_BAR_HEIGHT, TRUE); // Only show graph bar if it's completely visible // And Inventory is not selected. ajw if (s->y + s->cy <= stats_area.cy && StatsGetCurrentGroup() != STATS_INVENTORY) { ShowWindow(s->hControl, SW_NORMAL); num_visible++; } else ShowWindow(s->hControl, SW_HIDE); height = s->cy; } // Show scrollbar if necessary if (has_scrollbar) { y = StatsGetButtonBorder(); MoveWindow(hStatsScroll, stats_area.cx - stats_scrollbar_width, y, stats_scrollbar_width, num_visible * height, FALSE); ShowWindow(hStatsScroll, SW_HIDE); SetScrollRange(hStatsScroll, SB_CTL, 0, num_stats - num_visible, TRUE); SetScrollPos(hStatsScroll, SB_CTL, top_stat, TRUE); if( StatsGetCurrentGroup() != STATS_INVENTORY ) // ajw ShowWindow(hStatsScroll, SW_SHOWNORMAL); } else ShowWindow(hStatsScroll, SW_HIDE); StatsDraw(); }
/* * DisplayNumericStat: Display the given numeric type stat from the current group on the * main window. */ void DisplayNumericStat(Statistic *s) { RECT r; HDC hdc; HFONT hOldFont; char *name, *str; AREA stats_area; AREA a; // ajw - Avoid drawing if Inventory is selected as the "group". if( StatsGetCurrentGroup() == STATS_INVENTORY ) return; StatsGetArea(&stats_area); r.left = 0; r.right = stats_area.cx / 2; r.top = s->y; r.bottom = r.top + s->cy; /* If stat is out of stats area, abort */ if (r.bottom > stats_area.cy || s->num <= top_stat) return; hdc = GetDC(hStats); // DrawWindowBackground(hdc, &r, stats_area.x + r.left, stats_area.y + r.top); DrawWindowBackgroundColor( pinventory_bkgnd(), hdc, &r, stats_area.x + r.left, stats_area.y + r.top, -1 ); hOldFont = (HFONT) SelectObject(hdc, GetFont(FONT_STATS)); SetBkMode(hdc, TRANSPARENT); name = LookupNameRsc(s->name_res); // Draw with drop shadow SetTextColor(hdc, GetColor(COLOR_STATSBGD)); DrawText(hdc, name, strlen(name), &r, DT_LEFT); OffsetRect(&r, 1, 1); SetTextColor(hdc, GetColor(COLOR_STATSFGD)); DrawText(hdc, name, strlen(name), &r, DT_LEFT); switch (s->numeric.tag) { case STAT_RES: r.left = stats_area.cx / 2; r.right = stats_area.cx; DrawWindowBackgroundColor( pinventory_bkgnd(), hdc, &r, stats_area.x + r.left, stats_area.y + r.top, -1 ); str = LookupNameRsc(s->numeric.value); DrawText(hdc, str, strlen(str), &r, DT_RIGHT); break; case STAT_INT: // Draw background around stat bar a.x = stats_area.cx / 2; a.cx = stats_bar_width; a.y = s->y + (s->cy - STATS_BAR_HEIGHT) / 2; a.cy = STATS_BAR_HEIGHT; InterfaceDrawBarBorder( pinventory_bkgnd(), hdc, &a ); break; } SelectObject(hdc, hOldFont); ReleaseDC(hStats, hdc); InvalidateRect( s->hControl, NULL, FALSE ); }
/* * StatListKey: User pressed a key on stat list box. * Return True iff key should NOT be passed on to Windows for default processing. */ Bool StatListKey(HWND hwnd, UINT key, Bool fDown, int cRepeat, UINT flags) { Bool held_down = (flags & 0x4000) ? True : False; /* Is key being held down? */ int old_top, new_top, old_pos, new_pos; UserDidSomething(); old_pos = ListBox_GetCurSel(hwnd); new_top = old_top = ListBox_GetTopIndex(hwnd); // Handle keys manually to prevent Windows from copying list box background, which would // cause background to flash when it's redrawn in the correct location. switch (key) { case VK_UP: WindowBeginUpdate(hwnd); new_pos = max(0, old_pos - 1); if (new_pos < old_top) new_top = new_pos; ListBox_SetTopIndex(hwnd, new_top); ListBox_SetCurSel(hwnd, new_pos); SetScrollPos(hwnd, SB_VERT, new_top, TRUE); WindowEndUpdate(hwnd); return True; case VK_DOWN: WindowBeginUpdate(hwnd); new_pos = min(old_pos + 1, ListBox_GetCount(hwnd) - 1); if (new_pos > old_top + num_visible) new_top = new_pos - num_visible; ListBox_SetTopIndex(hwnd, new_top); ListBox_SetCurSel(hwnd, new_pos); SetScrollPos(hwnd, SB_VERT, new_top, TRUE); WindowEndUpdate(hwnd); return True; case VK_PRIOR: WindowBeginUpdate(hwnd); new_pos = max(0, old_pos - num_visible); new_top = new_pos; ListBox_SetTopIndex(hwnd, new_top); ListBox_SetCurSel(hwnd, new_pos); SetScrollPos(hwnd, SB_VERT, new_top, TRUE); WindowEndUpdate(hwnd); return True; case VK_NEXT: WindowBeginUpdate(hwnd); new_pos = min(old_pos + num_visible, ListBox_GetCount(hwnd) - 1); new_top = new_pos - num_visible; ListBox_SetTopIndex(hwnd, new_top); ListBox_SetCurSel(hwnd, new_pos); SetScrollPos(hwnd, SB_VERT, new_top, TRUE); WindowEndUpdate(hwnd); return True; case VK_RETURN: // ajw { int iLabelLen = ListBox_GetTextLen( hwnd, old_pos ); char* pszLabel = (char*)SafeMalloc( ( iLabelLen + 1 ) * sizeof( char ) ); if( ListBox_GetText( hwnd, old_pos, pszLabel ) != LB_ERR ) { // ajwxxx Hard-coded group number constants for spells list. There may be a var that could be used instead. char* pszCommand; if( StatsGetCurrentGroup() == STATS_SPELLS ) { pszCommand = (char*)SafeMalloc( ( iLabelLen + 6 ) * sizeof( char ) ); strcpy( pszCommand, "zaubern " ); } else { pszCommand = (char*)SafeMalloc( ( iLabelLen + 9 ) * sizeof( char ) ); strcpy( pszCommand, "perform " ); } strcat( pszCommand, pszLabel ); PerformAction( A_GOTOMAIN, NULL ); // For targeting icon to appear, focus must be on main view window. PerformAction( A_TEXTCOMMAND, pszCommand ); SafeFree( pszCommand ); } SafeFree( pszLabel ); } return True; } return StatInputKey(hwnd, key, fDown, cRepeat, flags); }