mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
454 lines
11 KiB
C++
454 lines
11 KiB
C++
/*
|
|
* Descent 3
|
|
* Copyright (C) 2024 Parallax Software
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
--- HISTORICAL COMMENTS FOLLOW ---
|
|
|
|
* $Logfile: /DescentIII/Main/ui/UIEdit.cpp $
|
|
* $Revision: 33 $
|
|
* $Date: 10/21/99 3:30p $
|
|
* $Author: Kevin $
|
|
*
|
|
* Edit control
|
|
*
|
|
* $Log: /DescentIII/Main/ui/UIEdit.cpp $
|
|
*
|
|
* 33 10/21/99 3:30p Kevin
|
|
* mac merge
|
|
*
|
|
* 32 5/17/99 5:19p Samir
|
|
* added ability for edit box to autoselect when hitting the max number of
|
|
* characters typable.
|
|
*
|
|
* 31 5/06/99 1:24a Samir
|
|
* upped editbox maxlength to 512
|
|
*
|
|
* 30 5/06/99 1:20a Samir
|
|
* allow editboxes with max buffer length of 280
|
|
*
|
|
* 29 4/28/99 1:54a Samir
|
|
* visual tweaks to text
|
|
*
|
|
* 28 4/21/99 12:42p Samir
|
|
* change some communication betwen UIEdit and child classes.
|
|
*
|
|
* 27 4/20/99 11:46a Samir
|
|
* numerous ui 'feel' fixes.
|
|
*
|
|
* 26 4/14/99 1:52a Jeff
|
|
* fixed case mismatched #includes
|
|
*
|
|
* 25 2/28/99 3:25a Samir
|
|
* added flag to input only numbers.
|
|
*
|
|
* 24 2/21/99 6:36p Samir
|
|
* focusing changes and key input changes to ui.,
|
|
*
|
|
* 23 10/19/98 12:18p Samir
|
|
* made tabbing between edit controls possible.
|
|
*
|
|
* 22 10/17/98 11:26a Samir
|
|
* fixed some edit box scrolling issues.
|
|
*
|
|
* 21 10/13/98 8:23p Samir
|
|
* communication between gadget and window and edit system to work
|
|
* together.
|
|
*
|
|
* 20 10/06/98 7:30p Samir
|
|
* activate listbox when created.
|
|
*
|
|
* 19 9/30/98 4:33p Samir
|
|
* disabled gadgets display dim text.
|
|
*
|
|
* 18 9/24/98 1:13p Samir
|
|
* edit box a bit better.
|
|
*
|
|
* 17 9/14/98 11:22a Samir
|
|
* enhanced editboxes
|
|
*
|
|
* 16 8/26/98 12:25p Samir
|
|
* fixed the whole editbox, keyboard access mess.
|
|
*
|
|
* 15 8/25/98 5:36p Samir
|
|
* added call to lock key focus in Activate too.
|
|
*
|
|
* 14 8/25/98 5:27p Samir
|
|
* new focusing rules for keyboard.
|
|
*
|
|
* 13 6/22/98 7:31p Samir
|
|
* added UIEdit::Activate, which activates an edit box manually.
|
|
*
|
|
* 12 6/22/98 3:46p Samir
|
|
* fixed bug in UIEdit password system.
|
|
*
|
|
* 11 6/22/98 2:52p Samir
|
|
* call Onselect for UIEdit boxes if edit is pressed.
|
|
*
|
|
* 10 6/22/98 2:15p Samir
|
|
* implemented border flag.
|
|
*
|
|
* 9 6/15/98 5:27p Kevin
|
|
* Fixed bug in UIEdit::GetText where m_TextBuf was NULL
|
|
*
|
|
* 8 5/25/98 8:17p Samir
|
|
* fixed some UI bugs with edit boxes.
|
|
*
|
|
* 7 4/13/98 7:02p Samir
|
|
* made some things protected.
|
|
*
|
|
* 6 3/10/98 11:03a Jeff
|
|
* changed strcpy to strncpy in GetText
|
|
*
|
|
* 5 1/30/98 7:05p Samir
|
|
* Each gadget now has their own coordinate system.
|
|
*
|
|
* 4 1/18/98 4:23p Samir
|
|
* Moved object destruction code to a virtual OnDestroy function for
|
|
* gadgets. Must destroy window too.
|
|
*
|
|
* 3 1/13/98 4:27p Samir
|
|
* Keyboard timing delay stored UIGadget. Moved from UIEdit.
|
|
*
|
|
* 2 1/05/98 4:36p Samir
|
|
* Moved centering and fittext control flags to UIGadget class.
|
|
*
|
|
* 1 1/02/98 12:49p Samir
|
|
* Initial revision.
|
|
*
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <cstdlib>
|
|
|
|
#include "UIlib.h"
|
|
#include "grtext.h"
|
|
#include "log.h"
|
|
#include "Macros.h"
|
|
#include "mem.h"
|
|
|
|
|
|
static UIEdit *UI_current_editbox = NULL;
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// UIEdit
|
|
// A single line edit control.
|
|
|
|
UIEdit::UIEdit() {
|
|
m_TextBuf = NULL;
|
|
m_BufSize = 0;
|
|
m_FontHandle = -1;
|
|
}
|
|
|
|
UIEdit::~UIEdit() {}
|
|
|
|
void UIEdit::Create(UIWindow *parent, int id, int x, int y, int w, int h, int flags) {
|
|
m_BufSize = 32;
|
|
m_TextBuf = (char *)mem_malloc(m_BufSize + 1);
|
|
m_TextBuf[0] = 0;
|
|
m_CursorPosX = 0;
|
|
m_Color = GR_WHITE;
|
|
m_Active = false;
|
|
m_StartPos = -1;
|
|
m_CurPos = 0;
|
|
UIGadget::Create(parent, id, x, y, w, h, flags);
|
|
SetTextBounds(2, m_W - 2, 0);
|
|
m_ScrollThresh = 0;
|
|
m_UpdateCount = false;
|
|
// UIEdit::Activate();
|
|
}
|
|
|
|
void UIEdit::SetTextBounds(int x1, int x2, int yoff) {
|
|
m_X1b = x1;
|
|
m_X2b = x2;
|
|
m_Yb = yoff;
|
|
}
|
|
|
|
void UIEdit::SetColor(ddgr_color col) { m_Color = col; }
|
|
|
|
#define EDIT_BUFLEN_MAX 1025 // DAJ utb 512
|
|
|
|
// setings
|
|
// sets the length of the input buffer.
|
|
void UIEdit::SetBufferLen(int length) {
|
|
char *newbuf;
|
|
ASSERT(length < EDIT_BUFLEN_MAX); // there are several places in the code that depend on something like this.
|
|
|
|
newbuf = (char *)mem_malloc(length + 1);
|
|
strncpy(newbuf, m_TextBuf, length);
|
|
newbuf[length] = 0;
|
|
if (m_TextBuf) {
|
|
mem_free(m_TextBuf);
|
|
}
|
|
m_TextBuf = newbuf;
|
|
m_BufSize = length;
|
|
m_UpdateCount = false;
|
|
}
|
|
|
|
// sets the text buffer.
|
|
void UIEdit::SetText(const char *text) {
|
|
ASSERT(strlen(text) <= (unsigned)m_BufSize);
|
|
|
|
if (CHECK_FLAG(m_Flags, UIED_NUMBERS)) {
|
|
int num = atoi(text);
|
|
sprintf(m_TextBuf, "%d", num);
|
|
} else {
|
|
strcpy(m_TextBuf, text);
|
|
}
|
|
|
|
m_CurPos = strlen(m_TextBuf);
|
|
m_StartPos = -1;
|
|
m_UpdateCount = false;
|
|
}
|
|
|
|
// retrieve text in edit control.
|
|
void UIEdit::GetText(char *buffer, int len) {
|
|
// ASSERT(strlen(m_TextBuf) < (unsigned)len);
|
|
if (!m_TextBuf) {
|
|
buffer[0] = '\0';
|
|
return;
|
|
}
|
|
strncpy(buffer, m_TextBuf, len - 1);
|
|
buffer[len - 1] = 0;
|
|
}
|
|
|
|
// sets font of control (default is window's font.)
|
|
void UIEdit::SetFont(int font) { m_FontHandle = font; }
|
|
|
|
void UIEdit::Activate() {
|
|
if (UI_current_editbox) {
|
|
UI_current_editbox->Deactivate();
|
|
}
|
|
|
|
m_Wnd->HoldHotkeys();
|
|
m_Active = true;
|
|
UI_current_editbox = this;
|
|
m_UpdateCount = false;
|
|
|
|
// mprintf(0, "activating edit box\n");
|
|
}
|
|
|
|
// deactivates edit box (use if you know what you're doing.)
|
|
void UIEdit::Deactivate() {
|
|
// mprintf(0, "deactivating edit box\n");
|
|
|
|
m_Active = false;
|
|
UI_current_editbox = NULL;
|
|
m_Wnd->ResumeHotkeys();
|
|
}
|
|
|
|
// Overrides
|
|
|
|
void UIEdit::OnDestroy() {
|
|
UIGadget::OnDestroy();
|
|
|
|
if (m_TextBuf) {
|
|
mem_free(m_TextBuf);
|
|
}
|
|
|
|
// if editbox is being destroyed and is the current editbox, reset to NULL.
|
|
if (UI_current_editbox == this)
|
|
UI_current_editbox = NULL;
|
|
}
|
|
|
|
// override: behavior when gadget loses input focus.
|
|
void UIEdit::OnLostFocus() {
|
|
// mprintf(0, "Edit control lost focus.\n");
|
|
UIEdit::Deactivate();
|
|
}
|
|
|
|
// override: behavior when gadget gains input focus.
|
|
void UIEdit::OnGainFocus() {
|
|
// mprintf(0, "Edit control gained focus.\n");
|
|
}
|
|
|
|
// behavior when gadget is being drawn.
|
|
void UIEdit::OnDraw() {
|
|
if (m_Flags & UIF_BORDER) {
|
|
ui_DrawBox(GR_RGB(128, 128, 128), m_X1b - 1, 0, m_X2b + 1, m_H);
|
|
}
|
|
|
|
DrawText();
|
|
}
|
|
|
|
void UIEdit::DrawText() {
|
|
char buffer[EDIT_BUFLEN_MAX];
|
|
int str_w, i, cursor_w;
|
|
|
|
if (m_FontHandle > -1)
|
|
ui_DrawSetFont(m_FontHandle);
|
|
|
|
// I need an extra character.
|
|
ASSERT(strlen(m_TextBuf) < sizeof(buffer));
|
|
|
|
if (m_Flags & UIED_PASSWORD) {
|
|
memset(buffer, '*', strlen(m_TextBuf));
|
|
buffer[strlen(m_TextBuf)] = 0;
|
|
} else {
|
|
strcpy(buffer, m_TextBuf);
|
|
}
|
|
|
|
if (m_Active || HasFocus())
|
|
ui_SetCharAlpha(255);
|
|
else
|
|
ui_SetCharAlpha(164);
|
|
|
|
if (IsDisabled())
|
|
ui_SetCharAlpha(96);
|
|
|
|
// we must set StartPos if StartPos is -1
|
|
if (m_StartPos < 0) {
|
|
m_StartPos = 0;
|
|
cursor_w = ui_GetTextWidth("_");
|
|
str_w = ui_GetTextWidth(&buffer[m_StartPos]);
|
|
while ((m_X1b + str_w) > (m_X2b - cursor_w)) {
|
|
m_StartPos++;
|
|
str_w = ui_GetTextWidth(&buffer[m_StartPos]);
|
|
}
|
|
}
|
|
|
|
// determine how much of string to draw at one time.
|
|
i = 0;
|
|
|
|
cursor_w = ui_GetTextWidth("_") * 2;
|
|
str_w = ui_GetTextWidth(&buffer[m_StartPos]);
|
|
while ((m_X1b + str_w) > (m_X2b - cursor_w) && ((int)strlen(buffer) > m_StartPos)) {
|
|
buffer[strlen(buffer) - 1] = 0;
|
|
str_w = ui_GetTextWidth(&buffer[m_StartPos]);
|
|
i++;
|
|
}
|
|
|
|
// if i is > 0, then the string displayed overlaps the boundaries of the listbox
|
|
m_ScrollThresh = i ? (strlen(buffer)) : 0;
|
|
|
|
if (m_ScrollThresh && m_UpdateCount) {
|
|
m_StartPos++;
|
|
m_UpdateCount = false;
|
|
}
|
|
|
|
// if cursor position is outside viewing region, we must adjust the viewing region.
|
|
// i = strlen(buffer);
|
|
// while (m_CurPos > i)
|
|
// m_CurPos--;
|
|
|
|
ui_DrawSetTextType(0);
|
|
ui_DrawString(m_Color, m_X1b, m_Yb + (m_H / 2 - ui_GetFontHeight() / 2), &buffer[m_StartPos]);
|
|
|
|
if (m_Active) {
|
|
buffer[m_CurPos] = 0;
|
|
str_w = ui_GetTextWidth(buffer + m_StartPos);
|
|
if (((int)UI_TIME()) % 2)
|
|
ui_DrawString(m_Color, m_X1b + str_w + 1, m_Yb + (m_H / 2 - ui_GetFontHeight() / 2), "_");
|
|
}
|
|
}
|
|
|
|
// behavior when key is pressed.
|
|
void UIEdit::OnKeyDown(int key) {
|
|
int ascii = grfont_KeyToAscii(m_FontHandle, key);
|
|
int len = strlen(m_TextBuf);
|
|
int i;
|
|
|
|
if (!m_Active) {
|
|
UIEdit::Activate();
|
|
}
|
|
|
|
if (key == KEY_ESC || key == KEY_ENTER) {
|
|
UIEdit::Deactivate();
|
|
if (key == KEY_ENTER) {
|
|
UIGadget::OnSelect(); // do this to enforce pressing enter ONLY causes OnSelect to work.
|
|
}
|
|
} else if (key == KEY_DELETE) {
|
|
for (i = m_CurPos; i < len; i++)
|
|
m_TextBuf[i] = m_TextBuf[i + 1];
|
|
} else {
|
|
if (m_CurPos < m_BufSize) {
|
|
if (CHECK_FLAG(m_Flags, UIED_NUMBERS)) {
|
|
if (ascii < '0' || ascii > '9') {
|
|
goto skip_add_to_buffer;
|
|
}
|
|
}
|
|
|
|
if (ascii >= 32 && ascii < 127 && len < m_BufSize) {
|
|
// insert character
|
|
for (i = len; i >= m_CurPos; i--)
|
|
m_TextBuf[i + 1] = m_TextBuf[i];
|
|
// adjust scroll region if cursor will go out of visible region.
|
|
LOG_DEBUG.printf("scroll=%d, curpos=%d", m_ScrollThresh, m_CurPos);
|
|
// if (m_ScrollThresh<=m_CurPos && m_ScrollThresh)
|
|
// m_StartPos++;
|
|
m_TextBuf[m_CurPos++] = (char)ascii;
|
|
m_UpdateCount = true;
|
|
if (m_CurPos == m_BufSize && CHECK_FLAG(m_Flags, UIED_AUTOSELECT)) {
|
|
UIEdit::Deactivate();
|
|
UIGadget::OnSelect();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
skip_add_to_buffer:
|
|
if (m_CurPos < len) {
|
|
if (key == KEY_RIGHT) {
|
|
if (m_ScrollThresh <= m_CurPos && m_ScrollThresh) {
|
|
m_StartPos++;
|
|
}
|
|
// Update_count = true;
|
|
m_CurPos++;
|
|
}
|
|
}
|
|
|
|
if (m_CurPos > 0) {
|
|
if (key == KEY_LEFT) {
|
|
m_CurPos--;
|
|
} else if (key == KEY_BACKSP) {
|
|
// delete character
|
|
for (i = m_CurPos - 1; i < len; i++)
|
|
m_TextBuf[i] = m_TextBuf[i + 1];
|
|
|
|
m_CurPos--;
|
|
}
|
|
if (m_CurPos < m_StartPos)
|
|
m_StartPos = m_CurPos;
|
|
}
|
|
}
|
|
}
|
|
|
|
// behavior when key is released.
|
|
void UIEdit::OnKeyUp(int key) {}
|
|
|
|
// behavior when mouse button is pressed.
|
|
void UIEdit::OnMouseBtnDown(int btn) {
|
|
if (btn == UILMSEBTN) {
|
|
if (!m_Active) {
|
|
UIEdit::Activate();
|
|
} else if (!PT_IN_GADGET(m_Wnd, this, UI_input.mx, UI_input.my) && m_Wnd->GetFocus()) {
|
|
// click outside control and in another control, then deactivate, this means we've accepted the input.
|
|
UIEdit::Deactivate();
|
|
}
|
|
}
|
|
}
|
|
|
|
// behavior when mouse button is released.
|
|
void UIEdit::OnMouseBtnUp(int btn) {}
|
|
|
|
void UIEdit::OnSelect() {
|
|
// except do this to release key focus on this edit box.
|
|
UIEdit::Deactivate();
|
|
UIGadget::OnSelect();
|
|
}
|