# File Name: makefile
# Author: Seree Rakwong
# Date: 28-NOV-2017
#
TARGET = tui_test
CC = gcc
CFLAGS = -g -Wall
LFLAGS = -lm -lcurses
.PHONY: default all clean
default: $(TARGET)
all: default
BIN_DIR = ./bin
SRC_DIR = ./src
INC_DIR = ./include
SOURCES = $(SRC_DIR)/tui.c \
$(SRC_DIR)/tdc.c \
$(SRC_DIR)/tmsgbx.c \
$(SRC_DIR)/tstc.c \
$(SRC_DIR)/tedt.c \
$(SRC_DIR)/tbtn.c \
$(SRC_DIR)/tlb.c \
$(SRC_DIR)/tlctl.c \
$(SRC_DIR)/tui_test.c
OBJECTS = $(SOURCES:.c=.o)
INCLUDES = -I$(INC_DIR)
DEFINES = -D__UNIX__ -D__LINUX__
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) -c $< -o $@
$(TARGET): $(OBJECTS)
$(CC) $(CFLAGS) $(LFLAGS) -o $@ $^
clean:
rm -f src/*.o $(TARGET)*
##############################################
# File Name: makefile
# Author: Seree Rakwong
# Date: 28-NOV-2017
#
TARGET = tui_test_sol8
CC = gcc
CFLAGS = -g -Wall
LFLAGS = -lm -lcurses
.PHONY: default all clean
default: $(TARGET)
all: default
BIN_DIR = ./bin
SRC_DIR = ./src
INC_DIR = ./include
SOURCES = $(SRC_DIR)/tui.c \
$(SRC_DIR)/tdc.c \
$(SRC_DIR)/tmsgbx.c \
$(SRC_DIR)/tstc.c \
$(SRC_DIR)/tedt.c \
$(SRC_DIR)/tbtn.c \
$(SRC_DIR)/tlb.c \
$(SRC_DIR)/tlctl.c \
$(SRC_DIR)/tui_test.c
OBJECTS = $(SOURCES:.c=.o)
INCLUDES = -I$(INC_DIR)
DEFINES = -D__UNIX__ -D__USE_CURSES__
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) -c $< -o $@
$(TARGET): $(OBJECTS)
$(CC) $(CFLAGS) $(LFLAGS) -o $@ $^
clean:
rm -f src/*.o $(TARGET)*
# File Name: makefile
# Author: Seree Rakwong
# Date: 28-NOV-2017
#
TARGET = tui_test_sol8
CC = gcc
CFLAGS = -g -Wall
LFLAGS = -lm -lcurses
.PHONY: default all clean
default: $(TARGET)
all: default
BIN_DIR = ./bin
SRC_DIR = ./src
INC_DIR = ./include
SOURCES = $(SRC_DIR)/tui.c \
$(SRC_DIR)/tdc.c \
$(SRC_DIR)/tmsgbx.c \
$(SRC_DIR)/tstc.c \
$(SRC_DIR)/tedt.c \
$(SRC_DIR)/tbtn.c \
$(SRC_DIR)/tlb.c \
$(SRC_DIR)/tlctl.c \
$(SRC_DIR)/tui_test.c
OBJECTS = $(SOURCES:.c=.o)
INCLUDES = -I$(INC_DIR)
DEFINES = -D__UNIX__ -D__USE_CURSES__
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) -c $< -o $@
$(TARGET): $(OBJECTS)
$(CC) $(CFLAGS) $(LFLAGS) -o $@ $^
clean:
rm -f src/*.o $(TARGET)*
##############################################
# File Name: makefile
# Author: Seree Rakwong
# Date: 28-NOV-2017
#
TARGET = tui_test_linux
CC = gcc
CFLAGS = -g -Wall
LFLAGS = -lm -lcurses
.PHONY: default all clean
default: $(TARGET)
all: default
BIN_DIR = ./bin
SRC_DIR = ./src
INC_DIR = ./include
SOURCES = $(SRC_DIR)/tui.c \
$(SRC_DIR)/tdc.c \
$(SRC_DIR)/tmsgbx.c \
$(SRC_DIR)/tstc.c \
$(SRC_DIR)/tedt.c \
$(SRC_DIR)/tbtn.c \
$(SRC_DIR)/tlb.c \
$(SRC_DIR)/tlctl.c \
$(SRC_DIR)/tui_test.c
OBJECTS = $(SOURCES:.c=.o)
INCLUDES = -I$(INC_DIR)
DEFINES = -D__UNIX__ -D__LINUX__ -D__USE_CURSES__
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) -c $< -o $@
$(TARGET): $(OBJECTS)
$(CC) $(CFLAGS) $(LFLAGS) -o $@ $^
clean:
rm -f src/*.o $(TARGET)*
/*-------------------------------------------------------------------
* File name: tui.h
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#ifndef __TEXTUSERINTERFACE_H__
#define __TEXTUSERINTERFACE_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-------------------------------------------------------------------
* defines
*-----------------------------------------------------------------*/
#define TUI_CONTINUE 1
#define TUI_OK 0
#define TUI_ERROR -1
#define TUI_MEM -2
/* miscellaneous */
#define TUI_MAX_WNDTEXT 80
#define TVK_BACK 0x08
#define TVK_TAB 0x09
#define TVK_ENTER 0x0A
#define TVK_SPACE 0x20
#define TVK_PRIOR 0x21
#define TVK_NEXT 0x22
#define TVK_END 0x23
#define TVK_HOME 0x24
#define TVK_LEFT 0x25
#define TVK_UP 0x26
#define TVK_RIGHT 0x27
#define TVK_DOWN 0x28
#define TVK_INSERT 0x2D
#define TVK_DELETE 0x2E
#define TVK_HELP 0x2F
#define TVK_ESCAPE 0x1B
#define TVK_NUMPAD0 0x60
#define TVK_NUMPAD1 0x61
#define TVK_NUMPAD2 0x62
#define TVK_NUMPAD3 0x63
#define TVK_NUMPAD4 0x64
#define TVK_NUMPAD5 0x65
#define TVK_NUMPAD6 0x66
#define TVK_NUMPAD7 0x67
#define TVK_NUMPAD8 0x68
#define TVK_NUMPAD9 0x69
#define TVK_MULTIPLY 0x6A
#define TVK_ADD 0x6B
#define TVK_SEPARATOR 0x6C
#define TVK_SUBTRACT 0x6D
#define TVK_DECIMAL 0x6E
#define TVK_DIVIDE 0x6F
#define TVK_F1 0x70
#define TVK_F2 0x71
#define TVK_F3 0x72
#define TVK_F4 0x73
#define TVK_F5 0x74
#define TVK_F6 0x75
#define TVK_F7 0x76
#define TVK_F8 0x77
#define TVK_F9 0x78
#define TVK_F10 0x79
#define TVK_F11 0x7A
#define TVK_F12 0x7B
#define TVK_F13 0x7C
#define TVK_F14 0x7D
#define TVK_F15 0x7E
#define TVK_F16 0x7F
#define TVK_F17 0x80
#define TVK_F18 0x81
#define TVK_F19 0x82
#define TVK_F20 0x83
#define TVK_F21 0x84
#define TVK_F22 0x85
#define TVK_F23 0x86
#define TVK_F24 0x87
/*
* 0x88 - 0x8F : unassigned
*/
#define TVK_NUMLOCK 0x90
#define TVK_SCROLL 0x91
/*-------------------------------------------------------------------
* types
*-----------------------------------------------------------------*/
typedef long WPARAM;
typedef long LPARAM;
typedef long LONG;
typedef int INT;
typedef void VOID;
typedef void* LPVOID;
typedef const char* LPCSTR;
typedef char* LPSTR;
typedef char CHAR;
typedef double DOUBLE;
typedef unsigned long DWORD;
typedef unsigned int UINT;
typedef char INT8;
typedef unsigned char UINT8;
typedef short INT16;
typedef unsigned short UINT16;
typedef int INT32;
typedef unsigned int UINT32;
typedef long long INT64;
typedef unsigned long long UINT64;
struct _TUIDEVICECONTEXSTRUCT;
typedef struct _TUIDEVICECONTEXSTRUCT _TDC;
typedef struct _TUIDEVICECONTEXSTRUCT *TDC;
struct _TUIWINDOWSTRUCT;
typedef struct _TUIWINDOWSTRUCT _TWND;
typedef struct _TUIWINDOWSTRUCT *TWND;
typedef long (*TWNDPROC)(TWND, UINT, WPARAM, LPARAM);
struct _TUIENVSTRUCT;
typedef struct _TUIENVSTRUCT _TENV;
typedef struct _TUIENVSTRUCT *TENV;
struct _WNDTEMPLSTRUCT
{
LPCSTR clsname;
LPCSTR text;
INT id;
INT y;
INT x;
INT lines;
INT cols;
DWORD style;
INT (*validate)(TWND, LPCSTR);
};
typedef struct _WNDTEMPLSTRUCT WNDTEMPL;
struct _MSGSTRUCT
{
TWND wnd;
UINT msg;
WPARAM wparam;
LPARAM lparam;
};
typedef struct _MSGSTRUCT MSG;
struct _NMHDRSTRUCT
{
INT id;
TWND ctl;
UINT code;
};
typedef struct _NMHDRSTRUCT NMHDR;
struct _RECTSTRUCT
{
INT y;
INT x;
INT lines;
INT cols;
};
typedef struct _RECTSTRUCT RECT;
struct _DRAWITEMSTRUCT
{
INT idx;
RECT rcitem;
};
typedef struct _DRAWITEMSTRUCT DRAWITEM;
/* colors */
/*
216 #define COLOR_BLACK 0
217 #define COLOR_RED 1
218 #define COLOR_GREEN 2
219 #define COLOR_YELLOW 3
220 #define COLOR_BLUE 4
221 #define COLOR_MAGENTA 5
222 #define COLOR_CYAN 6
223 #define COLOR_WHITE 7
*/
#define CYAN_BLACK 1
#define BLACK_CYAN 2
#define GREEN_BLACK 3
#define BLACK_GREEN 4
#define YELLOW_BLACK 5
#define BLACK_YELLOW 6
#define BLUE_YELLOW 7
#define YELLOW_BLUE 8
#define ALIGN_LEFT 0
#define ALIGN_CENTER 1
#define ALIGN_RIGHT 2
#define TW_HIDE 0
#define TW_SHOW 1
/* window styles */
#define TWS_WINDOW 0x00000001
#define TWS_CHILD 0x00000002
#define TWS_VISIBLE 0x00000004
#define TWS_ENABLE 0x00000008
#define TWS_DISABLED 0x00000010
#define TWS_LEFT 0x00000000 /* shared controls style */
#define TWS_CENTER 0x00010000
#define TWS_RIGHT 0x00020000
/* window messages */
#define TWM_FIRST 100
#define TWM_CREATE (TWM_FIRST + 1)
#define TWM_DESTROY (TWM_FIRST + 2)
#define TWM_INITDIALOG (TWM_FIRST + 3)
#define TWM_PAINT (TWM_FIRST + 4)
#define TWM_SETFOCUS (TWM_FIRST + 5)
#define TWM_KILLFOCUS (TWM_FIRST + 6)
#define TWM_KEYDOWN (TWM_FIRST + 7)
#define TWM_KEYUP (TWM_FIRST + 8)
#define TWM_CHAR (TWM_FIRST + 9)
#define TWM_NOTIFY (TWM_FIRST + 10)
#define TWM_ERASEBK (TWM_FIRST + 11)
#define TWM_SETTEXT (TWM_FIRST + 12)
#define TWM_GETTEXT (TWM_FIRST + 13)
#define TWM_SETTEXTALIGN (TWM_FIRST + 14)
#define TWM_COMMAND (TWM_FIRST + 15)
#define TWM_SETTEXTATTRS (TWM_FIRST + 16)
#define TWM_DRAWITEM (TWM_FIRST + 17)
/* application user messages */
#define TWM_USER 10000
/* notification control message */
#define TSN_FIRST (TWM_USER + 100)
#define TEN_FIRST (TWM_USER + 150)
#define TLBN_FIRST (TWM_USER + 200)
#define TBN_FIRST (TWM_USER + 250)
#define TLCN_FIRST (TWM_USER + 300)
/*-------------------------------------------------------------------
* static control
*-----------------------------------------------------------------*/
#define STATIC "STATIC"
#define TSS_LEFT TWS_LEFT
#define TSS_CENTER TWS_CENTER
#define TSS_RIGHT TWS_RIGHT
/*-------------------------------------------------------------------
* edit control
*-----------------------------------------------------------------*/
#define EDIT "EDIT"
#define TES_LEFT TWS_LEFT
#define TES_CENTER TWS_CENTER
#define TES_RIGHT TWS_RIGHT
#define TES_NUMBER 0x00040000
#define TES_UPPERCASE 0x00080000
#define TES_LOWERCASE 0x00100000
#define TES_PASSWORD 0x00200000
#define TES_APPENDMODE 0x00400000
#define TES_AUTOHSCROLL 0x00800000
#define TES_DECIMAL 0x01000000
#define TEM_LIMITTEXT (TWM_USER + 1)
#define TEM_SETPASSWDCHAR (TWM_USER + 2)
#define TEM_SHOWPASSWDCHAR (TWM_USER + 3)
#define TEM_SETDECWIDTH (TWM_USER + 4)
/* edit notified message */
#define TEN_CHANGED (TEN_FIRST + 0)
#define TEN_SETFOCUS (TEN_FIRST + 1)
#define TEN_KILLFOCUS (TEN_FIRST + 2)
/* edit macros */
#define TEDT_LimitText(edt, lim) \
TuiSendMsg(edt, TEM_LIMITTEXT, (WPARAM)lim, (LPARAM)0)
#define TEDT_SetPasswdChar(edt, ch) \
TuiSendMsg(edt, TEM_SETPASSWDCHAR, (WPARAM)ch, (LPARAM)0)
#define TEDT_ShowPasswdChar(edt, show) \
TuiSendMsg(edt, TEM_SHOWPASSWDCHAR, (WPARAM)show, (LPARAM)0)
#define TEDT_SetDecimalWidth(edt, wid) \
TuiSendMsg(edt, TEM_SETDECWIDTH, (WPARAM)wid, (LPARAM)0)
/*-------------------------------------------------------------------
* listbox control
*-----------------------------------------------------------------*/
#define LISTBOX "LISTBOX"
#define LB_OK TUI_OK
#define LB_ERROR TUI_ERROR
#define LB_UNCHECKED 0
#define LB_CHECKED 1
#define TLBS_LEFT TWS_LEFT
#define TLBS_CENTER TWS_CENTER
#define TLBS_RIGHT TWS_RIGHT
#define TLBS_OWNERDRAW 0x00100000
#define TLBS_CHECKBOX 0x00200000
#define TLBS_RADIOBOX 0x00400000
#define TLBM_ADDITEM (TWM_USER + 1)
#define TLBM_DELETEITEM (TWM_USER + 2)
#define TLBM_GETCURSEL (TWM_USER + 3)
#define TLBM_SETCURSEL (TWM_USER + 4)
#define TLBM_DELETEALLITEMS (TWM_USER + 5)
#define TLBM_GETITEMCOUNT (TWM_USER + 6)
#define TLBM_SETITEMDATA (TWM_USER + 7)
#define TLBM_GETITEMDATA (TWM_USER + 8)
#define TLBM_SETITEMTEXT (TWM_USER + 9)
#define TLBM_GETITEMTEXT (TWM_USER + 10)
#define TLBM_SETITEMCHECKED (TWM_USER + 11)
#define TLBM_GETITEMCHECKED (TWM_USER + 12)
#define TLBM_COUNTITEMCHECKED (TWM_USER + 13)
/* listbox notified message */
#define TLBN_SETFOCUS (TLBN_FIRST + 0)
#define TLBN_KILLFOCUS (TLBN_FIRST + 1)
#define TLBN_SELCHANGED (TLBN_FIRST + 2)
/* listbox macros */
#define TLB_AddItem(lbx, text) \
TuiSendMsg(lbx, TLBM_ADDITEM, (WPARAM)0, (LPARAM)text)
#define TLB_DeleteItem(lbx, idx) \
TuiSendMsg(lbx, TLBM_DELETEITEM, (WPARAM)idx, (LPARAM)0)
#define TLB_GetCurSel(lbx) \
TuiSendMsg(lbx, TLBM_GETCURSEL, (WPARAM)0, (LPARAM)0)
#define TLB_SetCurSel(lbx, idx) \
TuiSendMsg(lbx, TLBM_SETCURSEL, (WPARAM)idx, (LPARAM)0)
#define TLB_DeleteAllItems(lbx) \
TuiSendMsg(lbx, TLBM_DELETEALLITEMS, (WPARAM)0, (LPARAM)0)
#define TLB_GetItemCount(lbx) \
TuiSendMsg(lbx, TLBM_GETITEMCOUNT, (WPARAM)0, (LPARAM)0)
#define TLB_SetItemData(lbx, idx, data) \
TuiSendMsg(lbx, TLBM_SETITEMDATA, (WPARAM)idx, (LPARAM)data)
#define TLB_GetItemData(lbx, idx) \
(LPVOID)TuiSendMsg(lbx, TLBM_GETITEMDATA, (WPARAM)idx, (LPARAM)0)
#define TLB_SetItemText(lbx, idx, text) \
TuiSendMsg(lbx, TLBM_SETITEMTEXT, (WPARAM)idx, (LPARAM)text)
#define TLB_GetItemText(lbx, idx, text) \
TuiSendMsg(lbx, TLBM_GETITEMTEXT, (WPARAM)idx, (LPARAM)text)
#define TLB_SetItemChecked(lbx, idx, check) \
TuiSendMsg(lbx, TLBM_SETITEMCHECKED, (WPARAM)idx, (LPARAM)check)
#define TLB_GetItemChecked(lbx, idx) \
TuiSendMsg(lbx, TLBM_GETITEMCHECKED, (WPARAM)idx, (LPARAM)0)
#define TLB_CountItemChecked(lbx) \
TuiSendMsg(lbx, TLBM_COUNTITEMCHECKED, (WPARAM)0, (LPARAM)0)
/*-------------------------------------------------------------------
* button control
*-----------------------------------------------------------------*/
#define BUTTON "BUTTON"
#define TBS_RELEASED 0x0000
#define TBS_PRESSED 0x0001
#define TBS_FOCUSED 0x0002
#define TBN_SETFOCUS (TBN_FIRST + 0)
#define TBN_KILLFOCUS (TBN_FIRST + 1)
/*-------------------------------------------------------------------
* listctrl control
*-----------------------------------------------------------------*/
#define LISTCTRL "LISTCTRL"
#define TLCM_ADDCOLUMN (TWM_USER + 1)
#define TLCM_DELETECOLUMN (TWM_USER + 2)
#define TLCM_DELETEALLCOLUMNS (TWM_USER + 3)
#define TLCM_ADDITEM (TWM_USER + 4)
#define TLCM_DELETEITEM (TWM_USER + 5)
#define TLCM_DELETEALLITEMS (TWM_USER + 6)
#define TLCM_SETITEM (TWM_USER + 7)
#define TLCM_GETITEM (TWM_USER + 8)
#define TLCM_GETITEMCOUNT (TWM_USER + 9)
/*
#define TLCN_FIRST (TWM_USER + 300)
*/
#define LCFM_TEXT 0x0001
#define LCFM_ATTRS 0x0002
#define LCFM_DATA 0x0004
struct _SUBITEMSTRUCT
{
INT col;
INT idx;
CHAR* text;
DWORD attrs;
VOID* data;
};
typedef struct _SUBITEMSTRUCT SUBITEM;
struct _HEADERITEMSTRUCT
{
CHAR* caption;
INT cols;
INT align;
DWORD attrs;
};
typedef struct _HEADERITEMSTRUCT HEADERITEM;
/* listctrl macros */
#define TLC_AddColumn(lc, text, width, al, at) \
do {\
HEADERITEM hdr; \
hdr.caption = text; \
hdr.cols = width; \
hdr.align = al; \
hdr.attrs = at; \
TuiSendMsg(lc, TLCM_ADDCOLUMN, (WPARAM)0, (LPARAM)&hdr); \
} while (0)
#define TLC_DeleteColumn(lc, col) \
TuiSendMsg(lc, TLCM_DELETECOLUMN, (WPARAM)col, (LPARAM)0)
#define TLC_DeleteAllColumns(lc) \
TuiSendMsg(lc, TLCM_DELETEALLCOLUMNS, (WPARAM)0, (LPARAM)0)
#define TLC_AddItem(lc, text, nitems) \
TuiSendMsg(lc, TLCM_ADDITEM, (WPARAM)nitems, (LPARAM)text)
#define TLC_DeleteItem(lc, idx) \
TuiSendMsg(lc, TLCM_DELETEITEM, (WPARAM)idx, (LPARAM)0)
#define TLC_DeleteAllItems(lc) \
TuiSendMsg(lc, TLCM_DELETEALLITEMS, (WPARAM)0, (LPARAM)0)
#define TLC_SetItem(lc, flags, item) \
TuiSendMsg(lc, TLCM_SETITEMTEXT, (WPARAM)flags, (LPARAM)&subitem)
#define TLC_GetItem(lc, flags, item) \
TuiSendMsg(lc, TLCM_GETITEMTEXT, (WPARAM)flags, (LPARAM)&subitem);
#define TLC_GetItemCount(lc) \
TuiSendMsg(lc, TLCM_GETITEMCOUNT, (WPARAM)0, (LPARAM)0)
/*-------------------------------------------------------------------
* window functions
*-----------------------------------------------------------------*/
/*
* TuiStartup()
* Start TUI environment
*/
LONG TuiStartup();
/*
* TuiShutdown()
* End TUI environment
*/
void TuiShutdown();
/*
* TuiGetEnv()
* Get TUI environment
*/
TENV TuiGetEnv();
VOID TuiSetNextMove(LONG nextmove);
UINT TuiGetDlgMsgID();
/* window message functions */
LONG TuiDefWndProc(TWND, UINT, WPARAM, LPARAM);
LONG TuiRegisterCls(LPCSTR clsname, TWNDPROC wndproc);
LONG TuiGetMsg(MSG* msg);
LONG TuiDispatchMsg(MSG* msg);
LONG TuiTranslateMsg(MSG* msg);
LONG TuiPostQuitMsg(LONG exitcode);
LONG TuiSendMsg(TWND, UINT, WPARAM, LPARAM);
LONG TuiPostMsg(TWND, UINT, WPARAM, LPARAM);
/* window functions */
TWND TuiCreateWnd(
LPCSTR clsname,
LPCSTR wndname,
DWORD style,
INT y,
INT x,
INT lines,
INT cols,
TWND parent,
INT id,
LPVOID param
);
TWND TuiCreateWndTempl(
WNDTEMPL* templs,
LPVOID param
);
void TuiDestroyWnd(TWND);
TWND TuiGetActiveChildWnd(TWND);
TWND TuiGetFirstActiveChildWnd(TWND);
TWND TuiGetLastActiveChildWnd(TWND);
TWND TuiGetNextActiveChildWnd(TWND);
TWND TuiGetPrevActiveChildWnd(TWND);
TWND TuiGetActiveWnd();
TWND TuiGetFirstWnd();
TWND TuiGetLastWnd();
TWND TuiGetNextWnd(TWND wnd);
TWND TuiGetPrevWnd(TWND wnd);
LONG TuiInvalidateWnd(TWND);
LONG TuiShowWnd(TWND, LONG);
LONG TuiEnableWnd(TWND, LONG);
LONG TuiIsWndEnabled(TWND);
LONG TuiIsWndVisible(TWND);
TWND TuiGetWndItem(TWND, INT);
LONG TuiGetWndText(TWND, LPSTR, LONG);
VOID TuiSetWndText(TWND, LPCSTR);
TWND TuiGetParent(TWND);
LONG TuiSetFocus(TWND);
LONG TuiMoveWnd(TWND, INT, INT, INT, INT);
LONG TuiGetWndRect(TWND, RECT*);
DWORD TuiGetWndStyle(TWND);
DWORD TuiSetWndStyle(TWND, DWORD);
DWORD TuiGetWndTextAttrs(TWND);
DWORD TuiSetWndTextAttrs(TWND, DWORD);
UINT TuiGetWndID(TWND);
LPVOID TuiGetWndParam(TWND);
LPVOID TuiSetWndParam(TWND, LPVOID);
LONG TuiIsWndValidate(TWND, LPCSTR);
VOID TuiSetWndValidate(TWND, LONG (*)(TWND, LPCSTR));
#define MB_INVALID 0x00000000
#define MB_CAPTION 0x00010000
#define MB_YES 0x00000001
#define MB_NO 0x00000002
#define MB_CANCEL 0x00000004
#define MB_YESNOCANCEL (MB_YES|MB_NO|MB_CANCEL)
#define MB_YESNO (MB_YES|MB_NO)
#define MB_OK 0x00000008
#define MB_OKCANCEL (MB_OK|MB_CANCEL)
UINT TuiEndDlg(TWND, UINT);
UINT TuiMsgBox(TWND, LPCSTR, LPCSTR, UINT);
/* device context */
#define DT_LEFT 0x0001
#define DT_CENTER 0x0002
#define DT_RIGHT 0x0003
struct _TUIDEVICECONTEXSTRUCT
{
#ifdef __USE_CURSES__
WINDOW* win;
#elif defined __USE_QIO__
/* QIO for VMS implement here */
struct qio_fields* win;
#endif
};
TDC TuiGetDC(TWND);
LONG TuiDrawText(TDC, INT, INT, LPCSTR, DWORD);
LONG TuiDrawTextEx(TDC, INT, INT, INT, LPCSTR, LONG, DWORD, INT);
LONG TuiPutChar(TDC, INT, INT, CHAR, DWORD);
LONG TuiMoveYX(TDC, INT, INT);
LONG TuiGetYX(TDC, INT*, INT*);
LONG TuiPrintTextAlignment(LPSTR out, LPSTR in, LONG limit, INT align);
/* simple macros */
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#ifdef __cplusplus
}
#endif
#endif /*__TEXTUSERINTERFACE_H__*/
/*-------------------------------------------------------------------
* File name: tui.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
struct _TWNDPROCSTRUCT
{
TWNDPROC wndproc;
LPCSTR clsname;
struct _TWNDPROCSTRUCT *prev;
struct _TWNDPROCSTRUCT *next;
};
typedef struct _TWNDPROCSTRUCT twndproc_t;
struct _TUIMSGQUEUESTRUCT
{
TWND wnd;
UINT msg;
WPARAM wparam;
LPARAM lparam;
struct _TUIMSGQUEUESTRUCT *next;
};
typedef struct _TUIMSGQUEUESTRUCT tmsgq_t;
struct _TUIENVSTRUCT
{
/* doubly linked-list */
twndproc_t* firstproc;
twndproc_t* lastproc;
/* que */
tmsgq_t* headq;
tmsgq_t* tailq;
/* doubly linked-list */
TWND firstwnd;
TWND lastwnd;
TWND activewnd;
LONG quitcode;
LONG exitcode;
LONG nextmove; /* to identify the next control moved */
LONG prevmove; /* to identify the prev control moved */
LONG notifykey;
_TDC dc;
/* last dialog returned message */
UINT dlgmsgid;
};
struct _TUIWINDOWSTRUCT
{
LPCSTR clsname;
CHAR wndname[TUI_MAX_WNDTEXT+1];
DWORD style;
DWORD exstyle;
INT x;
INT y;
INT cols;
INT lines;
TWND parent;
UINT id;
LPVOID param;
TWNDPROC wndproc;
LONG enable;
LONG visible;
LONG (*validate)(TWND, LPCSTR);
/* curses lib */
#ifdef __USE_CURSES__
WINDOW* win;
#elif defined __USE_QIO__
/* QIO for VMS implement here */
struct qio_fields* win;
#endif
DWORD attrs;
/* last dialog returned message */
UINT dlgmsgid;
/* links */
TWND prevwnd;
TWND nextwnd;
TWND firstchild;
TWND lastchild;
TWND activechild;
};
/*-------------------------------------------------------------------
* global storages
*-----------------------------------------------------------------*/
TENV genvptr = 0;
/*-------------------------------------------------------------------
* internal functions
*-----------------------------------------------------------------*/
twndproc_t* _TuiFindWndProc(LPCSTR clsname);
TWND _TuiCreateWnd(
LPCSTR clsname,
LPCSTR wndname,
DWORD style,
INT y,
INT x,
INT lines,
INT cols,
TWND parent,
UINT id,
LPVOID param
);
VOID _TuiDestroyWnd(TWND wnd);
LONG _TuiInvalidateWnd(TWND wnd);
LONG _TuiDequeMsg();
LONG _TuiRemoveAllMsgs();
LONG _TuiAlignmentPrint(LPSTR out, LPSTR in, LONG limit, INT align);
LONG STATICPROC(TWND, UINT, WPARAM, LPARAM);
LONG EDITPROC(TWND, UINT, WPARAM, LPARAM);
LONG LISTBOXPROC(TWND, UINT, WPARAM, LPARAM);
LONG BUTTONPROC(TWND, UINT, WPARAM, LPARAM);
LONG LISTCTRLPROC(TWND, UINT, WPARAM, LPARAM);
#define MSGBOX "MSGBOX"
LONG MSGBOXPROC(TWND, UINT, WPARAM, LPARAM);
/*-------------------------------------------------------------------
* functions
*-----------------------------------------------------------------*/
#ifdef __USE_QIO__
int printf(const char *format, ...);
int sprintf(char *str, const char *format, ...);
LONG QIO_Initialize();
VOID QIO_Get();
VOID QIO_Put();
VOID DoUpdate() /* required by QIO */
{
return;
}
VOID CheckTerm() /* required by QIO */
{
return;
}
#endif /*__USE_QIO__*/
LONG TuiStartup()
{
TENV env = (TENV)malloc(sizeof(_TENV));
if (env)
{
genvptr = env;
memset(env, 0, sizeof(_TENV));
/* register standard controls */
TuiRegisterCls(STATIC, STATICPROC);
TuiRegisterCls(EDIT, EDITPROC);
TuiRegisterCls(LISTBOX, LISTBOXPROC);
TuiRegisterCls(BUTTON, BUTTONPROC);
TuiRegisterCls(LISTCTRL, LISTCTRLPROC);
TuiRegisterCls(MSGBOX, MSGBOXPROC);
/* device context */
#ifdef __USE_CURSES__
/* curses lib */
initscr();
cbreak();
keypad(stdscr, TRUE);
noecho();
start_color();
init_pair(CYAN_BLACK, COLOR_CYAN, COLOR_BLACK);
init_pair(BLACK_CYAN, COLOR_BLACK, COLOR_GREEN);
init_pair(GREEN_BLACK, COLOR_GREEN, COLOR_BLACK);
init_pair(BLACK_GREEN, COLOR_BLACK, COLOR_GREEN);
init_pair(YELLOW_BLACK, COLOR_YELLOW, COLOR_BLACK);
init_pair(BLACK_YELLOW, COLOR_BLACK, COLOR_YELLOW);
init_pair(BLUE_YELLOW, COLOR_BLUE, COLOR_YELLOW);
init_pair(YELLOW_BLUE, COLOR_YELLOW, COLOR_BLUE);
env->dc.win = stdscr;
env->nextmove = TVK_ENTER;
env->prevmove = KEY_BTAB;
env->notifykey = TVK_ENTER;
#elif defined __USE_QIO__
/* QIO for VMS implement here */
if (!QIO_Initialize())
{
free(env);
genvptr = 0;
}
env->dc.win = &qio_field;
#endif
}
return (genvptr ? TUI_OK : TUI_ERROR);
}
VOID TuiShutdown()
{
TWND wnd = genvptr->firstwnd;
TWND temp = 0;
while (wnd)
{
temp = wnd;
wnd = wnd->nextwnd;
TuiDestroyWnd(temp);
}
free(genvptr);
genvptr = 0;
#ifdef __USE_CURSES__
echo();
nocbreak();
endwin();
#elif defined __USE_QIO__
/* QIO for VMS implement here */
#endif
}
twndproc_t* _TuiFindWndProc(LPCSTR clsname)
{
TENV env = genvptr;
twndproc_t* proc = env->firstproc;
while (proc)
{
if (strcmp(proc->clsname, clsname) == 0)
{
break;
}
proc = proc->next;
}
return proc;
}
TENV TuiGetEnv()
{
return genvptr;
}
VOID TuiSetNextMove(LONG nextmove)
{
TENV env = genvptr;
env->nextmove = nextmove;
}
UINT TuiGetDlgMsgID()
{
TENV env = genvptr;
return env->dlgmsgid;
}
TDC TuiGetDC(TWND wnd)
{
static _TDC dc;
#ifdef __USE_CURSES__
if (wnd)
{
dc.win = wnd->win;
}
else
{
dc.win = stdscr;
}
#elif defined __USE_QIO__
/* QIO for VMS implement here */
if (wnd)
{
dc.win = wnd->win;
}
else
{
dc = genvptr->dc;
}
#endif
return (TDC)&dc;
}
LONG TuiRegisterCls(LPCSTR clsname, TWNDPROC wndproc)
{
TENV env = genvptr;
twndproc_t* proc = _TuiFindWndProc(clsname);
if (!proc)
{
proc = (twndproc_t*)malloc(sizeof(twndproc_t));
proc->clsname = clsname;
proc->wndproc = wndproc;
proc->prev = 0;
proc->next = 0;
if (env->firstproc)
{
proc->prev = env->lastproc;
env->lastproc->next = proc;
env->lastproc = proc;
}
else
{
env->firstproc = env->lastproc = proc;
}
}
return TUI_OK;
}
LONG TuiMoveWnd(TWND wnd, INT y, INT x, INT lines, INT cols)
{
LONG rc = TUI_OK;
wnd->y = y;
wnd->x = x;
wnd->lines = lines;
wnd->cols = cols;
return rc;
}
TWND _TuiCreateWnd(
LPCSTR clsname,
LPCSTR wndname,
DWORD style,
INT y,
INT x,
INT lines,
INT cols,
TWND parent,
UINT id,
LPVOID param
)
{
TENV env = genvptr;
TWND wnd = 0;
LONG len = 0;
twndproc_t* proc = _TuiFindWndProc(clsname);
if ((style & TWS_WINDOW) &&
(style & TWS_CHILD))
{
/* not allow creating both styles at a time */
return wnd;
}
else if (style & TWS_CHILD && !parent)
{
/* not allow child without parent */
return wnd;
}
if (proc)
{
wnd = (TWND)malloc(sizeof(_TWND));
if (wnd)
{
memset(wnd, 0, sizeof(_TWND));
wnd->clsname = clsname;
len = strlen(wndname);
if (wndname && len > 0)
{
if (len > TUI_MAX_WNDTEXT)
{
strncpy(wnd->wndname, wndname, TUI_MAX_WNDTEXT);
}
else
{
strcpy(wnd->wndname, wndname);
}
}
wnd->style = style;
wnd->parent = parent;
wnd->id = id;
wnd->wndproc = proc->wndproc;
wnd->enable = (style & TWS_DISABLED ? 0 : 1);
wnd->visible = (style & TWS_VISIBLE ? 1 : 0);
wnd->validate = 0;
/* curses */
#ifdef __USE_CURSES__
wnd->win = stdscr;
#elif defined __USE_QIO__
/* QIO for VMS implement here */
wnd->win = &qio_field;
#endif
wnd->attrs = 0;
/* make link */
if (style & TWS_WINDOW)
{
if (env->firstwnd)
{
wnd->prevwnd = env->lastwnd;
env->lastwnd->nextwnd = wnd;
env->lastwnd = wnd;
}
else
{
env->firstwnd = env->lastwnd = wnd;
}
env->activewnd = wnd;
env->dlgmsgid = MB_INVALID;
#ifdef __USE_CURSES__
wnd->y = (y > 0 && y < LINES ? y : 0);
wnd->x = (x > 0 && x < COLS ? x : 0);
wnd->lines = (lines > 0 && lines < LINES ? lines : LINES);
wnd->cols = (cols > 0 && cols < COLS ? cols : COLS);
#elif defined __USE_QIO__
/* QIO for VMS implement here */
wnd->y = y;
wnd->x = x;
wnd->lines = lines;
wnd->cols = cols;
#endif
}
else if (style & TWS_CHILD)
{
if (parent->firstchild)
{
wnd->prevwnd = parent->lastchild;
parent->lastchild->nextwnd = wnd;
parent->lastchild = wnd;
}
else
{
parent->firstchild = parent->lastchild = wnd;
}
/* re-size window rectangle */
wnd->y = (parent->y + y);
wnd->x = (parent->x + x);
wnd->lines = (lines > parent->lines ? parent->lines : lines);
wnd->cols = (cols > parent->cols ? parent->cols : cols);
/* send message */
TuiSendMsg(wnd, TWM_ERASEBK, (WPARAM)TuiGetDC(wnd), 0);
TuiSendMsg(wnd, TWM_CREATE, 0, 0);
}
}
}
return wnd;
}
TWND TuiCreateWnd(
LPCSTR clsname,
LPCSTR wndname,
DWORD style,
INT y,
INT x,
INT lines,
INT cols,
TWND parent,
INT id,
LPVOID param
)
{
LONG rc = TUI_CONTINUE;
TWND child = 0;
TWND wnd = _TuiCreateWnd(
clsname,
wndname,
style,
y,
x,
lines,
cols,
parent,
id,
param
);
if (wnd)
{
TuiSendMsg(wnd, TWM_ERASEBK, (WPARAM)TuiGetDC(wnd), 0);
rc = TuiSendMsg(wnd, TWM_CREATE, 0, (LPARAM)param);
if (rc != TUI_CONTINUE)
{
if (wnd)
{
_TuiDestroyWnd(wnd);
}
wnd = 0;
}
child = TuiGetFirstActiveChildWnd(wnd);
if (child)
{
wnd->activechild = child;
TuiSetFocus(child);
}
}
return wnd;
}
TWND TuiCreateWndTempl(
WNDTEMPL* templs,
LPVOID param
)
{
LONG rc = TUI_CONTINUE;
TWND wnd = 0;
TWND child = 0;
int i = 0;
if (templs)
{
wnd = _TuiCreateWnd(
templs[i].clsname,
templs[i].text,
templs[i].style,
templs[i].y,
templs[i].x,
templs[i].lines,
templs[i].cols,
0,
0,
param
);
if (wnd)
{
for (i = 1; templs[i].clsname; ++i)
{
child = _TuiCreateWnd(
templs[i].clsname,
templs[i].text,
templs[i].style,
templs[i].y,
templs[i].x,
templs[i].lines,
templs[i].cols,
wnd,
templs[i].id,
0
);
if (!child)
{
_TuiDestroyWnd(wnd);
wnd = 0;
}
else
{
child->validate = (LONG (*)(TWND, LPCSTR))templs[i].validate;
}
} /* create children */
} /* wnd is created successfully */
if (wnd)
{
TuiSendMsg(wnd, TWM_ERASEBK, (WPARAM)TuiGetDC(wnd), 0);
rc = TuiSendMsg(wnd, TWM_INITDIALOG, (WPARAM)0, (LPARAM)0);
if (rc != TUI_CONTINUE)
{
_TuiDestroyWnd(wnd);
wnd = 0;
}
child = TuiGetFirstActiveChildWnd(wnd);
if (child)
{
wnd->activechild = child;
TuiSetFocus(child);
}
}
} /* templs is allocated */
return wnd;
}
void _TuiDestroyWnd(TWND wnd)
{
TWND child = (wnd ? wnd->firstchild : 0);
TWND temp = child;
while (child)
{
child = child->nextwnd;
free(temp);
temp->nextwnd = temp->prevwnd = 0;
temp = child;
}
wnd->nextwnd = wnd->prevwnd = 0;
free(wnd);
}
void TuiDestroyWnd(TWND wnd)
{
TENV env = genvptr;
/* remove the link if it is TWS_WINDOW */
if (wnd->style & TWS_WINDOW)
{
env->lastwnd = wnd->prevwnd;
if (env->lastwnd)
{
env->lastwnd->nextwnd = 0;
}
env->activewnd = env->lastwnd;
}
/* save the last message id */
env->dlgmsgid = wnd->dlgmsgid;
TuiSendMsg(wnd, TWM_DESTROY, 0, 0);
_TuiDestroyWnd(wnd);
if (env->activewnd)
{
TuiInvalidateWnd(env->activewnd);
}
}
LONG TuiPostMsg(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (wnd)
{
tmsgq_t* msgq = (tmsgq_t*)malloc(sizeof(tmsgq_t));
if (msgq)
{
TENV env = genvptr;
memset(msgq, 0, sizeof(tmsgq_t));
msgq->wnd = wnd;
msgq->msg = msg;
msgq->wparam = wparam;
msgq->lparam = lparam;
if (env->tailq)
{
env->tailq->next = msgq;
}
else
{
env->headq = env->tailq = msgq;
}
return TUI_OK;
}
}
return TUI_ERROR;
}
LONG TuiSendMsg(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (wnd)
{
/*
TENV env = genvptr;
tmsgq_t* msgq = 0;
while (env->headq)
{
msgq = env->headq;
msgq->wnd->wndproc(msgq->wnd,
msgq->msg,
msgq->wparam,
msgq->lparam);
env->headq = env->headq->next;
free(msgq);
}
env->headq = env->tailq = 0;
*/
return wnd->wndproc(wnd, msg, wparam, lparam);
}
return TUI_ERROR;
}
LONG _TuiInvalidateWnd(TWND wnd)
{
TWND activechild = TuiGetActiveChildWnd(wnd);
TWND child = wnd->firstchild;
TuiSendMsg(wnd, TWM_ERASEBK, (WPARAM)TuiGetDC(wnd), 0);
TuiSendMsg(wnd, TWM_PAINT, 0, 0);
while (child)
{
TuiSendMsg(child, TWM_ERASEBK, (WPARAM)TuiGetDC(wnd), 0);
TuiSendMsg(child, TWM_PAINT, 0, 0);
child = child->nextwnd;
}
if (!activechild)
{
activechild = TuiGetFirstActiveChildWnd(wnd);
}
if (activechild)
{
TuiMoveYX(TuiGetDC(activechild), activechild->y, activechild->x);
}
return TUI_OK;
}
LONG TuiInvalidateWnd(TWND wnd)
{
return _TuiInvalidateWnd(wnd);
}
LONG TuiShowWnd(TWND wnd, LONG show)
{
wnd->visible = show;
return _TuiInvalidateWnd(wnd);
}
LONG TuiEnableWnd(TWND wnd, LONG enable)
{
wnd->enable = enable;
return _TuiInvalidateWnd(wnd);
}
TWND TuiGetFirstActiveChildWnd(TWND wnd)
{
if (wnd)
{
TWND activechild = wnd->activechild;
TWND firstwnd = 0;
wnd->activechild = wnd->lastchild;
firstwnd = TuiGetNextActiveChildWnd(wnd);
wnd->activechild = activechild;
return firstwnd;
}
return 0;
}
TWND TuiGetLastActiveChildWnd(TWND wnd)
{
if (wnd)
{
TWND activechild = wnd->activechild;
TWND lastwnd = 0;
wnd->activechild = wnd->firstchild;
lastwnd = TuiGetPrevActiveChildWnd(wnd);
wnd->activechild = activechild;
return lastwnd;
}
return 0;
}
TWND TuiGetPrevActiveChildWnd(TWND wnd)
{
TWND activechild = (wnd ? wnd->activechild : 0);
if (!activechild && wnd)
{
activechild = wnd->lastchild;
}
else if (activechild)
{
activechild = activechild->prevwnd;
if (!activechild && wnd)
{
activechild = wnd->lastchild;
}
}
while (activechild)
{
if (TuiIsWndVisible(activechild))
{
if (TuiIsWndEnabled(activechild))
{
if (strcmp(activechild->clsname, STATIC) != 0)
{
break; /* found the next control */
}
}
}
activechild = activechild->prevwnd;
}
return activechild;
}
TWND TuiGetActiveChildWnd(TWND wnd)
{
TWND parent = (wnd ? wnd->parent : 0);
return (wnd ? wnd->activechild : parent);
}
TWND TuiGetNextActiveChildWnd(TWND wnd)
{
TWND activechild = (wnd ? wnd->activechild : 0);
if (!activechild && wnd)
{
activechild = wnd->firstchild;
}
else if (activechild)
{
activechild = activechild->nextwnd;
if (!activechild && wnd)
{
activechild = wnd->firstchild;
}
}
while (activechild)
{
if (TuiIsWndVisible(activechild))
{
if (TuiIsWndEnabled(activechild))
{
if (strcmp(activechild->clsname, STATIC) != 0)
{
break; /* found the next control */
}
}
}
activechild = activechild->nextwnd;
}
return activechild;
}
LONG TuiIsWndEnabled(TWND wnd)
{
if (!wnd)
{
return TUI_ERROR;
}
return wnd->enable;
}
LONG TuiIsWndVisible(TWND wnd)
{
if (!wnd)
{
return TUI_ERROR;
}
return wnd->visible;
}
TWND TuiGetWndItem(TWND wnd, INT id)
{
TWND child = wnd->firstchild;
while (child)
{
if (child->id == id)
{
break;
}
child = child->nextwnd;
}
return child;
}
LONG TuiGetWndRect(TWND wnd, RECT* rect)
{
rect->y = wnd->y;
rect->x = wnd->x;
rect->lines = wnd->lines;
rect->cols = wnd->cols;
return TUI_OK;
}
DWORD TuiGetWndTextAttrs(TWND wnd)
{
return wnd->attrs;
}
DWORD TuiSetWndTextAttrs(TWND wnd, DWORD newattrs)
{
DWORD oldattrs = wnd->attrs;
wnd->attrs = newattrs;
return oldattrs;
}
DWORD TuiGetWndStyle(TWND wnd)
{
return wnd->style;
}
DWORD TuiSetWndStyle(TWND wnd, DWORD newstyle)
{
DWORD oldstyle = wnd->style;
wnd->style = newstyle;
return oldstyle;
}
UINT TuiGetWndID(TWND wnd)
{
return wnd->id;
}
LPVOID TuiGetWndParam(TWND wnd)
{
return wnd->param;
}
LPVOID TuiSetWndParam(TWND wnd, LPVOID newparam)
{
LPVOID oldparam = wnd->param;
wnd->param = newparam;
return oldparam;
}
LONG TuiIsWndValidate(TWND wnd, LPCSTR text)
{
LONG rc = TUI_CONTINUE;
if (wnd->validate)
{
rc = wnd->validate(wnd, text);
}
return rc;
}
VOID
TuiSetWndValidate(TWND wnd, LONG (*validate)(TWND, LPCSTR))
{
wnd->validate = validate;
}
LONG TuiGetWndText(TWND wnd, LPSTR text, LONG cb)
{
LONG len = (wnd ? strlen(wnd->wndname) : 0);
if (cb < 0)
{
return len;
}
memset(text, 0, cb);
if (cb > len)
{
cb = len;
}
strncpy(text, wnd->wndname, cb);
return strlen(text);
}
VOID TuiSetWndText(TWND wnd, LPCSTR text)
{
LONG len = 0;
if (text && wnd)
{
len = strlen(text);
if (len > TUI_MAX_WNDTEXT)
{
strncpy(wnd->wndname, text, TUI_MAX_WNDTEXT);
}
else
{
strcpy(wnd->wndname, text);
}
TuiInvalidateWnd(wnd);
}
}
TWND TuiGetParent(TWND wnd)
{
if (wnd)
{
return wnd->parent;
}
return 0;
}
/*-------------------------------------------------------------------
* MSG functions
*-----------------------------------------------------------------*/
#ifdef __USE_QIO__
VOID QIO_GetCh()
{
QIO_InitParameter();
while(1)
{
QIO_GetKeyTerminal();
switch(bProcess)
{
case ENDERR:
printf("Program abort...\n");
exit(0);
case BEGPROC:
QIO_InitParameter();
break;
case ENDSUCC:
CheckProcessInput();
if(CheckValue()== TRUE)
{
memset(qio_field.szDefault,0,SIZE_TEXT);
return;
}
}
}
}
#endif
LONG TuiGetMsg(MSG* msg)
{
TENV env = genvptr;
tmsgq_t* msgq = 0;
if (env->quitcode)
{
return 0;
}
/* deque */
while (env->headq)
{
msgq = env->headq;
msgq->wnd->wndproc(msgq->wnd,
msgq->msg,
msgq->wparam,
msgq->lparam);
env->headq = env->headq->next;
free(msgq);
}
env->tailq = env->headq; /* set to nil */
memset(msg, 0, sizeof(MSG));
msg->wnd = env->activewnd;
#ifdef __USE_CURSES__
msg->wparam = wgetch(stdscr);
#elif defined __USE_QIO__
/*printf("%s", sQioClear);*/
/*QIO_Text(5, 1, 'W', sPrompt);*/
qio_field.lType = QIO_ANY /*| QIO_UPPERCASE*/ | QIO_NO_ECHO;
qio_field.cColor = 'W';
/*sprintf(qio_field.szHelp, "%s", "Enter password");*/
/*strcpy(qio_field.szHelp, "");*/
qio_field.lLength = 1;
qio_field.lRow = 1;
qio_field.lColumn = 1;/*strlen(sPrompt)+1;*/
qio_field.bReprint = 0;
QIO_Get();
/*printf("\n");*/
/*
memcpy(sInput, qio_field.szResult, MAX_PUBKEY_LEN+MAX_LEN_PWD);
*/
msg->wparam = qio_field.lTerm;
#endif
return msg->wparam;
}
LONG _TuiAlignmentPrint(LPSTR out, LPSTR in, LONG limit, INT align)
{
LONG len = 0;
CHAR text[TUI_MAX_WNDTEXT+1];
INT firstlen = 0;
INT lastlen = 0;
len = strlen(in);
if (len > limit)
{
len = limit;
}
memset(text, 0, TUI_MAX_WNDTEXT);
if ((ALIGN_CENTER == align) || (TWS_CENTER & align))
{
firstlen = (limit - len)/2;
lastlen = limit - (len + firstlen);
if (firstlen > 0 && lastlen > 0)
{
sprintf(text, "%*s%s%*s",
firstlen, " ",
in,
lastlen, " ");
}
else if (lastlen > 0)
{
sprintf(text, "%s%*s",
in,
lastlen, " ");
}
else
{
sprintf(text, "%s", in);
}
}
else if ((ALIGN_RIGHT == align) || (TWS_RIGHT & align))
{
sprintf(text, "%*s",
(INT)(limit),
in);
}
else
{
sprintf(text, "%-*s",
(INT)(limit),
in);
}
strcpy(out, text);
return strlen(out);
}
LONG _TuiRemoveAllMsgs()
{
TENV env = genvptr;
tmsgq_t* msgq = 0;
/* deque */
while (env->headq)
{
msgq = env->headq;
if (env->headq)
{
env->headq = env->headq->next;
}
msgq->next = 0;
free(msgq);
}
env->tailq = env->headq = 0;
return TUI_OK;
}
LONG _TuiDequeMsg()
{
TENV env = genvptr;
tmsgq_t* msgq = 0;
/* deque */
while (env->headq)
{
msgq = env->headq;
TuiSendMsg(msgq->wnd,
msgq->msg,
msgq->wparam,
msgq->lparam);
if (env->headq)
{
env->headq = env->headq->next;
}
msgq->next = 0;
free(msgq);
}
env->tailq = env->headq = 0;
return TUI_OK;
}
LONG TuiDispatchMsg(MSG* msg)
{
TENV env = genvptr;
TWND wnd = env->activewnd;
TWND child = wnd->activechild;
if (env->quitcode)
{
return TUI_OK;
}
if (child)
{
msg->wnd = child;
}
else if (wnd)
{
child = TuiGetFirstActiveChildWnd(wnd);
if (child)
{
msg->wnd = child;
}
else
{
msg->wnd = wnd;
}
}
/* deque message */
_TuiDequeMsg();
return TUI_OK;
}
LONG TuiTranslateMsg(MSG* msg)
{
TENV env = genvptr;
INT ch = (int)msg->wparam;
LONG rc = 0;
TWND nextwnd = 0;
TWND prevwnd = 0;
TWND parent = 0;
LONG nextmove = env->nextmove;
LONG prevmove = env->prevmove;
if (env->quitcode)
{
return TUI_OK;
}
/* send message to the current active window */
if (!msg->wnd)
{
return TUI_CONTINUE;
}
/* convert keyboard code to message */
switch (ch)
{
#ifdef __USE_CURSES__
/* not support mouse/resize events yet */
case KEY_MOUSE:/* Mouse event has occurred */
#ifdef __LINUX__
case KEY_RESIZE:/* Terminal resize event */
#endif
#elif defined __USE_QIO__
#endif
return 0;
}
/*case TVK_ENTER:*/ /*ENTER*/
if (ch == nextmove)
{
parent = TuiGetParent(msg->wnd);
/* kill focus the current active window */
nextwnd = TuiGetNextActiveChildWnd(parent);
rc = TuiSendMsg(msg->wnd, TWM_KILLFOCUS, 0, (LPARAM)nextwnd);
if (rc != TUI_CONTINUE)
{
return rc;
}
/* set focus the new active window */
prevwnd = msg->wnd;
if (parent)
{
if (msg->wnd == TuiGetLastActiveChildWnd(parent))
{
msg->wnd = TuiGetFirstActiveChildWnd(parent);
}
else
{
msg->wnd = nextwnd;
}
parent->activechild = msg->wnd;
}
else
{
msg->wnd = TuiGetNextActiveChildWnd(env->activewnd);
env->activewnd->activechild = msg->wnd;
}
if (msg->wnd)
{
rc = TuiPostMsg(msg->wnd, TWM_SETFOCUS, 0, (LPARAM)prevwnd);
TuiMoveYX(TuiGetDC(msg->wnd), msg->wnd->y, msg->wnd->x);
}
return 0;
}
else if (ch == prevmove)
{
parent = TuiGetParent(msg->wnd);
/* kill focus the current active window */
prevwnd = TuiGetPrevActiveChildWnd(parent);
rc = TuiSendMsg(msg->wnd, TWM_KILLFOCUS, 0, (LPARAM)prevwnd);
if (rc != TUI_CONTINUE)
{
return rc;
}
/* set focus the new active window */
nextwnd = msg->wnd;
if (parent)
{
if (msg->wnd == TuiGetFirstActiveChildWnd(parent))
{
msg->wnd = TuiGetLastActiveChildWnd(parent);
}
else
{
msg->wnd = prevwnd;
}
parent->activechild = msg->wnd;
}
else
{
msg->wnd = TuiGetPrevActiveChildWnd(env->activewnd);
env->activewnd->activechild = msg->wnd;
}
if (msg->wnd)
{
rc = TuiPostMsg(msg->wnd, TWM_SETFOCUS, 0, (LPARAM)nextwnd);
TuiMoveYX(TuiGetDC(msg->wnd), msg->wnd->y, msg->wnd->x);
}
return 0;
}
/* parent window */
rc = TuiSendMsg(env->activewnd, TWM_KEYDOWN, msg->wparam, 0);
rc = TuiSendMsg(env->activewnd, TWM_CHAR, msg->wparam, 0);
rc = TuiSendMsg(env->activewnd, TWM_KEYUP, msg->wparam, 0);
if (msg->wnd != env->activewnd)
{
rc = TuiSendMsg(msg->wnd, TWM_KEYDOWN, msg->wparam, 0);
rc = TuiSendMsg(msg->wnd, TWM_CHAR, msg->wparam, 0);
rc = TuiSendMsg(msg->wnd, TWM_KEYUP, msg->wparam, 0);
}
/* deque */
/*
while (env->headq)
{
msgq = env->headq;
TuiSendMsg(msgq->wnd,
msgq->msg,
msgq->wparam,
msgq->lparam);
env->headq = env->headq->next;
free(msgq);
}
env->tailq = env->headq;
*/
TuiDispatchMsg(msg);
return 0;
}
LONG TuiPostQuitMsg(LONG exitcode)
{
TENV env = genvptr;
env->quitcode = 1;
env->exitcode = exitcode;
return TUI_OK;
}
LONG TuiSetFocus(TWND wnd)
{
TENV env = genvptr;
TWND parent = (wnd ? wnd->parent : env->activewnd);
TWND activewnd = TuiGetActiveChildWnd(wnd);
LONG rc = TUI_CONTINUE;
/* kill focus at the current control */
rc = TuiSendMsg(activewnd, TWM_KILLFOCUS, 0, (LPARAM)wnd);
if (rc != TUI_CONTINUE)
{
return rc;
}
if (wnd)
{
rc = TuiSendMsg(wnd, TWM_SETFOCUS, 0, (LPARAM)activewnd);
TuiMoveYX(TuiGetDC(wnd), wnd->y, wnd->x);
parent->activechild = wnd;
}
return rc;
}
TWND TuiGetActiveWnd()
{
TENV env = genvptr;
return env->activewnd;
}
TWND TuiGetFirstWnd()
{
TENV env = genvptr;
return env->firstwnd;
}
TWND TuiGetLastWnd()
{
TENV env = genvptr;
return env->lastwnd;
}
TWND TuiGetNextWnd(TWND wnd)
{
return wnd->nextwnd;
}
TWND TuiGetPrevWnd(TWND wnd)
{
return wnd->prevwnd;
}
LONG TuiPrintTextAlignment(LPSTR out, LPSTR in, LONG limit, INT align)
{
return _TuiAlignmentPrint(out, in, limit, align);
}
/*-------------------------------------------------------------------
* DefWndProc functions
*-----------------------------------------------------------------*/
LONG _TuiDefWndProc_OnEraseBk(TWND wnd, TDC dc);
VOID _TuiDefWndProc_OnSetText(TWND wnd, LPCSTR text);
LONG _TuiDefWndProc_OnGetText(TWND wnd, LPSTR text, LONG cb);
VOID _TuiDefWndProc_OnSetTextAlign(TWND wnd, INT align);
VOID _TuiDefWndProc_OnSetTextAttrs(TWND wnd, DWORD attrs);
LONG _TuiDefWndProc_OnEraseBk(TWND wnd, TDC dc)
{
INT i;
CHAR buf[TUI_MAX_WNDTEXT + 1];
RECT rc;
DWORD attrs = TuiGetWndTextAttrs(wnd);
if (TuiIsWndVisible(wnd))
{
TuiGetWndRect(wnd, &rc);
memset(buf, ' ', rc.cols);
buf[rc.cols] = 0;
for (i = 0; i < rc.lines; ++i)
{
TuiDrawText(dc, rc.y + i, rc.x, buf, attrs);
}
}
return TUI_OK;
}
VOID _TuiDefWndProc_OnSetText(TWND wnd, LPCSTR text)
{
LONG len = 0;
if (text)
{
len = strlen(text);
if (len > TUI_MAX_WNDTEXT)
{
strncpy(wnd->wndname, text, TUI_MAX_WNDTEXT);
}
else
{
strcpy(wnd->wndname, text);
}
}
}
LONG _TuiDefWndProc_OnGetText(TWND wnd, LPSTR text, LONG cb)
{
LONG len = strlen(wnd->wndname);
if (cb < 0 || !text)
{
return len;
}
if (cb > len)
{
cb = len;
}
memset(text, 0, cb);
strncpy(text, wnd->wndname, cb);
return strlen(text);
}
VOID _TuiDefWndProc_OnSetTextAlign(TWND wnd, INT align)
{
wnd->style &= ~(TWS_LEFT | TWS_CENTER | TWS_RIGHT);
if (ALIGN_CENTER == align)
{
wnd->style |= TWS_CENTER;
}
else if (ALIGN_RIGHT == align)
{
wnd->style |= TWS_RIGHT;
}
else
{
wnd->style |= TWS_LEFT;
}
}
VOID _TuiDefWndProc_OnSetTextAttrs(TWND wnd, DWORD attrs)
{
wnd->attrs = attrs;
}
LONG TuiDefWndProc(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_CREATE:
case TWM_KILLFOCUS:
return TUI_CONTINUE;
case TWM_ERASEBK:
{
return _TuiDefWndProc_OnEraseBk(wnd, (TDC)wparam);
}
case TWM_SETTEXT:
{
_TuiDefWndProc_OnSetText(wnd, (LPCSTR)lparam);
return 0;
}
case TWM_GETTEXT:
{
return _TuiDefWndProc_OnGetText(wnd, (LPSTR)lparam, (LONG)wparam);
}
case TWM_SETTEXTALIGN:
{
_TuiDefWndProc_OnSetTextAlign(wnd, (INT)wparam);
}
case TWM_SETTEXTATTRS:
{
_TuiDefWndProc_OnSetTextAttrs(wnd, (DWORD)wparam);
}
}
return TUI_OK;
}
UINT TuiMsgBox(TWND parent, LPCSTR caption, LPCSTR text, UINT flags)
{
MSG msg;
UINT rc = MB_INVALID;
TWND box = 0;
RECT rect;
LONG caplen = 0, textlen = 0, wndwidth = 0;
LONG nbtns = 0;
LONG btnwidth = 0;
INT i;
enum
{
Msgbox = 0,
CaptionStatic,
YesButton,
NoButton,
OKButton,
CancelButton,
EmptyCtl
};
WNDTEMPL msgbox[] =
{
{ MSGBOX, text, 0, 0, 1, 7, 1, TWS_WINDOW, 0 },
/* text */
{ STATIC, caption, MB_CAPTION, 0, 0, 1, 1, TWS_CHILD|TWS_VISIBLE|TSS_CENTER, 0 },
/* buttons */
{ BUTTON, "Yes", MB_YES, 0, 0, 1, 11, TWS_CHILD, 0 },
{ BUTTON, "No", MB_NO, 0, 0, 1, 10, TWS_CHILD, 0 },
{ BUTTON, "OK", MB_OK, 0, 0, 1, 10, TWS_CHILD, 0 },
{ BUTTON, "Cancel", MB_CANCEL, 0, 0, 1, 10, TWS_CHILD, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
/* calculate window width */
if (flags & MB_YES)
{
msgbox[YesButton].style |= TWS_VISIBLE;
++nbtns;
btnwidth += msgbox[YesButton].cols + 1;
}
else
{
msgbox[YesButton].style &= ~TWS_VISIBLE;
}
if (flags & MB_NO)
{
msgbox[NoButton].style |= TWS_VISIBLE;
++nbtns;
btnwidth += msgbox[NoButton].cols + 1;
}
else
{
msgbox[NoButton].style &= ~TWS_VISIBLE;
}
if (flags & MB_OK)
{
msgbox[OKButton].style |= TWS_VISIBLE;
++nbtns;
btnwidth += msgbox[OKButton].cols + 1;
}
else
{
msgbox[OKButton].style &= ~TWS_VISIBLE;
}
if (flags & MB_CANCEL)
{
msgbox[CancelButton].style |= TWS_VISIBLE;
btnwidth += msgbox[CancelButton].cols + 1;
++nbtns;
}
else
{
msgbox[CancelButton].style &= ~TWS_VISIBLE;
}
TuiGetWndRect(parent, &rect);
caplen = strlen(caption);
textlen = strlen(text);
wndwidth = MAX(btnwidth, MAX(caplen, textlen));
if (wndwidth % 2 == 1)
{
++wndwidth;
}
/* move window to center */
msgbox[Msgbox].lines = 7;
msgbox[Msgbox].y = rect.y + (rect.lines - msgbox[Msgbox].lines)/2;
msgbox[Msgbox].cols = wndwidth + 10;
msgbox[Msgbox].x = rect.x + (rect.cols - msgbox[Msgbox].cols)/2;
/* move caption to center */
msgbox[CaptionStatic].lines = 1;
msgbox[CaptionStatic].y = 1;
msgbox[CaptionStatic].x = 1;
msgbox[CaptionStatic].cols = msgbox[Msgbox].cols - 2;
/* move buttons to center */
if (nbtns > 3)
{
}
else if (nbtns > 0)
{
INT x = (msgbox[Msgbox].cols - btnwidth)/(nbtns == 1 ? 2 : nbtns);
for (i = YesButton; nbtns > 0 && i < EmptyCtl; ++i)
{
if (msgbox[i].style & TWS_VISIBLE)
{
/* move buttons */
msgbox[i].lines = 1;
msgbox[i].y = 5;
msgbox[i].x = x;
/* next button moved */
x += msgbox[i].cols + 1;
--nbtns;
}
}
}
box = TuiCreateWndTempl(msgbox, 0);
if (!box)
{
return -1;
}
TuiShowWnd(box, TW_SHOW);
/* remove all messages */
_TuiRemoveAllMsgs();
rc = TuiGetDlgMsgID();
while (rc == MB_INVALID)
{
TuiGetMsg(&msg);
TuiDispatchMsg(&msg);
TuiTranslateMsg(&msg);
rc = TuiGetDlgMsgID();
}
return rc;
}
UINT TuiEndDlg(TWND wnd, UINT id)
{
wnd->dlgmsgid = id;
TuiDestroyWnd(wnd);
return id;
}
/*-------------------------------------------------------------------
* File name: tdc.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* DC functions
*-----------------------------------------------------------------*/
LONG TuiPutChar(
TDC dc,
INT y,
INT x,
CHAR ch,
DWORD attrs)
{
#ifdef __USE_CURSES__
/* set attributes on */
attron(attrs);
/* print now */
mvwaddch(dc->win, y, x, ch);
/* set attributes off */
attroff(attrs);
#elif defined __USE_QIO__
/* QIO for VMS implement here */
dc->win->lType = QIO_ANY;
dc->win->cColor = 'W';
dc->win->lLength = 1;
dc->win->lRow = y;
dc->win->lColumn = x;
strcpy( dc->win->szHelp, "");
sprintf(dc->win->szText, "%c", ch);
QIO_Put();
#endif
return TUI_OK;
}
LONG TuiDrawTextEx(TDC dc, INT y, INT x, INT cols, LPCSTR text, LONG len, DWORD attrs, INT align)
{
if (DT_CENTER == align)
{
if (len)
{
return TuiDrawText(dc, y, x + (cols - len) / 2, text, attrs);
}
else
{
return TuiDrawText(dc, y, x, text, attrs);
}
}
else if (DT_RIGHT == align)
{
if (len < cols)
{
return TuiDrawText(dc, y, x + cols - len, text, attrs);
}
else
{
return TuiDrawText(dc, y, x, text, attrs);
}
}
return TuiDrawText(dc, y, x, text, attrs);
}
LONG TuiDrawText(
TDC dc,
INT y,
INT x,
LPCSTR text,
DWORD attrs)
{
#ifdef __USE_CURSES__
if (y >= LINES)
{
y = LINES - 1;
}
if (x >= COLS)
{
x = COLS - 1;
}
/* set attributes on */
attron(attrs);
/* print now */
mvwprintw(dc->win, y, x, text);
/* set attributes off */
attroff(attrs);
#elif defined __USE_QIO__
/* QIO for VMS implement here */
dc->win->lType = QIO_ANY;/*QIO_INTEGER | QIO_UPPERCASE;*/
dc->win->cColor = 'W';
dc->win->lLength = strlen(text);
dc->win->lRow = y;
dc->win->lColumn = x;
strcpy(dc->win->szHelp, "");
strcpy(dc->win->szText, text);
QIO_Put();
#endif
return TUI_OK;
}
LONG TuiMoveYX(TDC dc, INT y, INT x)
{
#ifdef __USE_CURSES__
wmove(dc->win, y, x);
#elif defined __USE_QIO__
/* QIO for VMS implement here */
dc->win->lRow = y;
dc->win->lColumn = x;
#endif
return TUI_OK;
}
LONG TuiGetYX(TDC dc, INT* y, INT* x)
{
int xx = 0, yy = 0;
#ifdef __USE_CURSES__
getyx(dc->win, yy, xx);
#elif defined __USE_QIO__
/* QIO for VMS implement here */
yy = dc->win->lRow;
xx = dc->win->lColumn;
#endif
*y = yy;
*x = xx;
return TUI_OK;
}
/*-------------------------------------------------------------------
* File name: tmsgbx.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* Message box functions
*-----------------------------------------------------------------*/
VOID TMSGB_OnPaint(TWND wnd, TDC dc);
VOID TMSGB_OnPaint(TWND wnd, TDC dc)
{
CHAR text[TUI_MAX_WNDTEXT+1];
CHAR buf[TUI_MAX_WNDTEXT+1];
RECT rc;
TuiGetWndRect(wnd, &rc);
TuiGetWndText(wnd, text, TUI_MAX_WNDTEXT);
TuiPrintTextAlignment(buf, text, rc.cols, ALIGN_CENTER);
TuiDrawText(dc, rc.y + 3, rc.x, buf, TuiGetWndTextAttrs(wnd));
}
LONG MSGBOXPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_INITDIALOG:
{
TWND btn = TuiGetFirstActiveChildWnd(wnd);
if (btn)
{
TuiSetFocus(btn);
}
#ifdef __USE_CURSES__
TuiSendMsg(wnd, TWM_SETTEXTATTRS, (WPARAM)(A_REVERSE), (LPARAM)0);
#endif
return TUI_CONTINUE;
}
case TWM_PAINT:
{
TMSGB_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
case TWM_COMMAND:
{
TuiEndDlg(wnd, (UINT)wparam);
break;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
/*-------------------------------------------------------------------
* File name: tstc.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* STATIC functions
*-----------------------------------------------------------------*/
VOID TSTC_OnPaint(TWND wnd, TDC dc);
LONG TSTC_OnCreate(TWND wnd);
LONG STATICPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
VOID TSTC_OnPaint(TWND wnd, TDC dc)
{
CHAR buf[TUI_MAX_WNDTEXT+1];
CHAR text[TUI_MAX_WNDTEXT+1];
RECT rc;
if (TuiIsWndVisible(wnd))
{
TuiGetWndRect(wnd, &rc);
TuiGetWndText(wnd, text, TUI_MAX_WNDTEXT);
TuiPrintTextAlignment(buf, text, rc.cols, TuiGetWndStyle(wnd));
TuiDrawText(dc, rc.y, rc.x, buf, TuiGetWndTextAttrs(wnd));
}
}
LONG TSTC_OnCreate(TWND wnd)
{
#ifdef __USE_CURSES__
TuiSetWndTextAttrs(wnd, COLOR_PAIR(GREEN_BLACK));
#elif defined __USE_QIO__
TuiSetWndTextAttrs(wnd, GREEN_BLACK);
#endif
return TUI_CONTINUE;
}
LONG STATICPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_CREATE:
{
/* initial memory for static control */
return TSTC_OnCreate(wnd);
}
case TWM_DESTROY:
{
/* release memory of static control */
return 0;
}
case TWM_PAINT:
{
TSTC_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
/*-------------------------------------------------------------------
* File name: tbtn.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* BUTTON functions
*-----------------------------------------------------------------*/
struct _TBUTTONSTRUCT
{
INT state;
};
typedef struct _TBUTTONSTRUCT _TBUTTON;
typedef struct _TBUTTONSTRUCT *TBUTTON;
LONG TBTN_OnCreate(TWND wnd);
VOID TBTN_OnPaint(TWND wnd, TDC dc);
VOID TBTN_OnSetFocus(TWND wnd);
LONG TBTN_OnKillFocus(TWND wnd);
VOID TBTN_OnDestroy(TWND wnd);
VOID TBTN_OnKeyDown(TWND wnd, LONG ch);
LONG BUTTONPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
VOID TBTN_OnPaint(TWND wnd, TDC dc)
{
LONG len = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
CHAR text[TUI_MAX_WNDTEXT+1];
DWORD attrs = TuiGetWndTextAttrs(wnd);
RECT rc;
TBUTTON btn = 0;
btn = (TBUTTON)TuiGetWndParam(wnd);
TuiGetWndRect(wnd, &rc);
if (TuiIsWndVisible(wnd))
{
TuiGetWndText(wnd, text, TUI_MAX_WNDTEXT);
len = TuiPrintTextAlignment(buf,
text,
rc.cols,
ALIGN_CENTER);
if (btn->state & TBS_FOCUSED)
{
buf[0] = '[';
buf[1] = '[';
buf[len-2] = ']';
buf[len-1] = ']';
}
else
{
buf[0] = '[';
buf[1] = ' ';
buf[len-2] = ' ';
buf[len-1] = ']';
}
if (!TuiIsWndEnabled(wnd))
{
#ifdef __USE_CURSES__
attrs = A_DIM|A_NORMAL;
#elif defined __USE_QIO__
attrs = 0;
#endif
}
else if (btn->state == TBS_RELEASED)
{
#ifdef __USE_CURSES__
attrs = A_REVERSE;
#elif defined __USE_QIO__
attrs = 0;
#endif
}
TuiDrawText(dc, rc.y, rc.x, buf, attrs);
}
TuiMoveYX(dc, rc.y, rc.x);
}
LONG TBTN_OnCreate(TWND wnd)
{
TBUTTON btn = 0;
/* initial memory for static control */
btn = (TBUTTON)malloc(sizeof(_TBUTTON));
if (!btn)
{
return TUI_ERROR;
}
btn->state = TBS_RELEASED;
TuiSetWndParam(wnd, (LPVOID)btn);
#ifdef __USE_CURSES__
TuiSetWndTextAttrs(wnd, COLOR_PAIR(CYAN_BLACK));
#elif defined __USE_QIO__
TuiSetWndTextAttrs(wnd, CYAN_BLACK);
#endif
return TUI_CONTINUE;
}
VOID TBTN_OnSetFocus(TWND wnd)
{
NMHDR nmhdr;
TBUTTON btn = (TBUTTON)TuiGetWndParam(wnd);
btn->state = TBS_FOCUSED; /* add state */
TuiInvalidateWnd(wnd);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TBN_SETFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
}
LONG TBTN_OnKillFocus(TWND wnd)
{
NMHDR nmhdr;
LONG rc = TUI_CONTINUE;
TBUTTON btn = (TBUTTON)TuiGetWndParam(wnd);
btn->state &= ~TBS_FOCUSED; /* remove state */
TuiInvalidateWnd(wnd);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TBN_KILLFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
return rc;
}
VOID TBTN_OnDestroy(TWND wnd)
{
TBUTTON btn = (TBUTTON)TuiGetWndParam(wnd);
free(btn);
}
VOID TBTN_OnKeyDown(TWND wnd, LONG ch)
{
TBUTTON btn = (TBUTTON)TuiGetWndParam(wnd);
INT repaint = 0;
switch (ch)
{
case TVK_SPACE:
repaint = 1;
break;
}
if (repaint)
{
btn->state = TBS_PRESSED;
TuiInvalidateWnd(wnd);
btn->state = TBS_RELEASED | TBS_FOCUSED;
TuiInvalidateWnd(wnd);
/* send notification */
TuiPostMsg(TuiGetParent(wnd),
TWM_COMMAND,
(WPARAM)TuiGetWndID(wnd),
(LPARAM)wnd);
}
}
LONG BUTTONPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_CREATE:
{
/* initial memory for static control */
return TBTN_OnCreate(wnd);
}
case TWM_DESTROY:
{
/* release memory of static control */
TBTN_OnDestroy(wnd);
return 0;
}
case TWM_SETFOCUS:
{
TBTN_OnSetFocus(wnd);
break;
}
case TWM_KILLFOCUS:
{
return TBTN_OnKillFocus(wnd);
}
case TWM_KEYDOWN:
{
TBTN_OnKeyDown(wnd, (LONG)wparam);
break;
}
case TWM_PAINT:
{
TBTN_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
/*-------------------------------------------------------------------
* File name: tedt.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* EDIT functions
*-----------------------------------------------------------------*/
struct _TEDITSTRUCT
{
CHAR editbuf[TUI_MAX_WNDTEXT+1];
INT firstvisit;
CHAR passchar;
INT showpass;
INT firstchar;
INT limitchars;
INT editing;
INT decwidth;
};
typedef struct _TEDITSTRUCT _TEDIT;
typedef struct _TEDITSTRUCT *TEDIT;
LONG TEDT_OnCreate(TWND wnd);
VOID TEDT_OnDestroy(TWND wnd);
VOID TEDT_OnSetFocus(TWND wnd);
LONG TEDT_OnKillFocus(TWND wnd);
LONG TEDT_ValidateNumberStyle(TWND wnd, TEDIT edit, LONG ch);
LONG TEDT_ValidateDecimalStyle(TWND wnd, TEDIT edit, LONG ch);
VOID TEDT_OnChar(TWND wnd, LONG ch);
VOID TEDT_OnPaint(TWND wnd, TDC dc);
VOID TEDT_OnLimitText(TWND wnd, INT limit);
VOID TEDT_OnSetPasswdChar(TWND wnd, CHAR passchar);
VOID TEDT_OnShowPasswdChar(TWND wnd, INT show);
VOID TEDT_OnSetDecWidth(TWND wnd, INT width);
LONG EDITPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
LONG TEDT_OnCreate(TWND wnd)
{
TEDIT edit = 0;
DWORD style = TuiGetWndStyle(wnd);
RECT rc;
/* initial memory for edit control */
edit = (TEDIT)malloc(sizeof(_TEDIT));
if (!edit)
{
return TUI_MEM;
}
TuiGetWndRect(wnd, &rc);
TuiGetWndText(wnd, edit->editbuf, TUI_MAX_WNDTEXT);
edit->firstvisit = 1;
edit->firstchar = 0;
edit->passchar = '*';
edit->showpass = TW_SHOW;
edit->editing = 0;
edit->decwidth = 6;
edit->limitchars = (TES_AUTOHSCROLL & style ? TUI_MAX_WNDTEXT : rc.cols);
TuiSetWndParam(wnd, (LPVOID)edit);
#ifdef __USE_CURSES__
TuiSetWndTextAttrs(wnd, COLOR_PAIR(CYAN_BLACK));
#elif defined __USE_QIO__
TuiSetWndTextAttrs(wnd, CYAN_BLACK);
#endif
return TUI_CONTINUE;
}
VOID TEDT_OnDestroy(TWND wnd)
{
TEDIT edit = 0;
/* release memory of edit control */
edit = (TEDIT)TuiGetWndParam(wnd);
free(edit);
}
VOID TEDT_OnSetFocus(TWND wnd)
{
TEDIT edit = 0;
NMHDR nmhdr;
/* save edited buffer */
edit = (TEDIT)TuiGetWndParam(wnd);
TuiGetWndText(wnd, edit->editbuf, TUI_MAX_WNDTEXT);
edit->firstvisit = 1;
edit->firstchar = 0;
edit->editing = 0;
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TEN_SETFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
}
LONG TEDT_OnKillFocus(TWND wnd)
{
TEDIT edit = 0;
NMHDR nmhdr;
LONG rc = TUI_CONTINUE;
CHAR buf[TUI_MAX_WNDTEXT + 1];
DOUBLE decimal = 0.0;
DWORD style = TuiGetWndStyle(wnd);
edit = (TEDIT)TuiGetWndParam(wnd);
rc = TuiIsWndValidate(wnd, buf);
if (rc != TUI_CONTINUE)
{
return rc;
}
/* check if style is TES_DECIMAL */
if (style & TES_DECIMAL)
{
decimal = atof(edit->editbuf);
sprintf(buf, "%.*f", edit->decwidth, decimal);
strcpy(edit->editbuf, buf);
}
/* update text */
edit->firstchar = 0;
edit->editing = 0;
TuiSetWndText(wnd, edit->editbuf);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TEN_KILLFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
TuiInvalidateWnd(wnd);
return rc;
}
LONG TEDT_ValidateNumberStyle(TWND wnd, TEDIT edit, LONG ch)
{
LONG rc = TUI_CONTINUE;
if (ch < '0' || ch > '9')
{
rc = TUI_ERROR;
}
return rc;
}
LONG TEDT_ValidateDecimalStyle(TWND wnd, TEDIT edit, LONG ch)
{
LONG rc = TUI_CONTINUE;
CHAR* decimal = strchr(edit->editbuf, '.');
LONG len = strlen(edit->editbuf);
/* not allowed '-' in the string */
if ((len > 0 && (edit->firstvisit == 0)) && ch == '-')
{
rc = TUI_ERROR;
}
if ((rc == TUI_CONTINUE) && (len == 0 || (edit->firstvisit == 1)) && ch == '-')
{
/* ok */
}
else if (ch == '.')
{
if (decimal)
{
/* not allowed having '.' more than one */
rc = TUI_ERROR;
}
}
else if (ch < '0' || ch > '9')
{
rc = TUI_ERROR;
}
else
{
}
return rc;
}
VOID TEDT_OnChar(TWND wnd, LONG ch)
{
TEDIT edit = 0;
NMHDR nmhdr;
INT changed = 0;
TDC dc = TuiGetDC(wnd);
LONG len = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
DWORD attrs = TuiGetWndTextAttrs(wnd);
CHAR text[TUI_MAX_WNDTEXT+1];
DWORD style = TuiGetWndStyle(wnd);
RECT rc;
LONG ret = TUI_CONTINUE;
edit = (TEDIT)TuiGetWndParam(wnd);
if (TuiIsWndEnabled(wnd))
{
#ifdef __USE_CURSES__
attrs |= A_UNDERLINE;
#elif defined __USE_QIO__
attrs |= 0;
#endif
}
TuiGetWndText(wnd, text, TUI_MAX_WNDTEXT);
TuiGetWndRect(wnd, &rc);
if (ch == TVK_ESCAPE)
{
if (edit->firstvisit == 0)
{
edit->firstvisit = 1;
strcpy(edit->editbuf, text);
edit->firstchar = 0;
edit->editing = 0;
TuiInvalidateWnd(wnd);
return;
}
}
if (ch >= 0x20 && ch < 0x7f)
{
/* add char */
len = strlen(edit->editbuf);
if (len + 1 <= edit->limitchars)
{
if (TES_NUMBER & style)
{
/* require only number input */
ret = TEDT_ValidateNumberStyle(wnd, edit, ch);
if (ret != TUI_CONTINUE)
{
return;
}
}
else if (TES_DECIMAL & style)
{
/* require only decimal input */
ret = TEDT_ValidateDecimalStyle(wnd, edit, ch);
if (ret != TUI_CONTINUE)
{
return;
}
}
else if (TES_UPPERCASE & style)
{
/* require changing from small to CAPITAL */
if (ch >= 'a' && ch <= 'z')
{
ch = ch - 'a' + 'A';
}
}
else if (TES_LOWERCASE & style)
{
if (ch >= 'A' && ch <= 'Z')
{
ch = ch - 'A' + 'a';
}
}
if (edit->firstvisit == 1)
{
edit->firstvisit = 0;
if (!(TES_APPENDMODE & style) || (TES_PASSWORD & style)) /* replace mode */
{
edit->editbuf[0] = 0;
memset(buf, ' ', rc.cols);
buf[rc.cols] = 0;
TuiDrawText(dc, rc.y, rc.x, buf, attrs);
TuiMoveYX(dc, rc.y, rc.x);
}
else if (TES_AUTOHSCROLL & style)
{
/* show first char at */
if (len > rc.cols)
{
edit->firstchar = len - rc.cols - 1;
}
}
}
/* append a new char */
len = strlen(edit->editbuf);
if (len < edit->limitchars)
{
edit->editbuf[len] = ch;
edit->editbuf[len+1] = 0;
if (len < rc.cols)
{
if (TES_PASSWORD & style)
{
if (edit->showpass == TW_SHOW)
{
TuiPutChar(dc, rc.y, rc.x + len,
edit->passchar,
attrs);
}
}
else
{
TuiPutChar(dc, rc.y, rc.x + len,
ch,
attrs);
}
}
changed = 1;
} /* len < limit */
if (TES_AUTOHSCROLL & style)
{
len = strlen(edit->editbuf);
if (len <= edit->limitchars && len > rc.cols && changed)
{
++edit->firstchar;
if (edit->firstchar > edit->limitchars - rc.cols)
{
edit->firstchar = edit->limitchars - rc.cols - 1;
}
TuiInvalidateWnd(wnd);
if ((TES_PASSWORD & style) && (edit->showpass == TW_SHOW))
{
TuiMoveYX(dc, rc.y, rc.x);
}
else
{
TuiMoveYX(dc, rc.y, rc.x + rc.cols);
}
}
}
/* editing */
edit->editing = 1;
} /*TUI_MAX_WNDTEXT*/
}
else if (ch == 0x7f || ch == TVK_DELETE ||
#ifdef __USE_CURSES__
ch == KEY_BACKSPACE) /* delete char */
#elif defined __USE_QIO__
ch == KEY_BS)
#endif
{
len = strlen(edit->editbuf);
if (edit->firstvisit == 1)
{
edit->firstvisit = 0;
if (!(TES_APPENDMODE & style) || TES_PASSWORD & style) /* replace mode */
{
edit->editbuf[0] = 0;
sprintf(buf, "%*s", rc.cols, " ");
TuiMoveYX(dc, rc.y, rc.x);
TuiDrawText(dc, rc.y, rc.x, buf, attrs);
}
else if (TES_AUTOHSCROLL & style)
{
/* show first char at */
if (len > rc.cols)
{
edit->firstchar = len - rc.cols - 1;
}
}
}
if (len > 0)
{
if (len > rc.cols)
{
TuiPutChar(dc, rc.y, rc.x + rc.cols - 1, ' ', attrs);
}
else
{
TuiPutChar(dc, rc.y, rc.x + len - 1, ' ', attrs);
}
TuiMoveYX(dc, rc.y, rc.x + len - 1);
edit->editbuf[len - 1] = 0;
changed = 1;
if (TES_AUTOHSCROLL & style)
{
len = strlen(edit->editbuf);
if (len >= rc.cols)
{
edit->firstchar = len - rc.cols;
if (edit->firstchar < 0)
{
edit->firstchar = 0;
}
len = rc.cols;
}
else
{
edit->firstchar = 0;
}
TuiInvalidateWnd(wnd);
TuiMoveYX(dc, rc.y, rc.x + len);
}
}
/* editing */
edit->editing = 1;
}
if (changed)
{
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TEN_CHANGED;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
}
}
VOID TEDT_OnPaint(TWND wnd, TDC dc)
{
TEDIT edit = 0;
LONG len = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
CHAR text[TUI_MAX_WNDTEXT+1];
DWORD attrs = TuiGetWndTextAttrs(wnd);
RECT rc;
DWORD style = TuiGetWndStyle(wnd);
edit = (TEDIT)TuiGetWndParam(wnd);
if (TuiIsWndEnabled(wnd))
{
#ifdef __USE_CURSES__
attrs |= A_UNDERLINE;
#elif defined __USE_QIO__
attrs |= 0;
#endif
}
TuiGetWndRect(wnd, &rc);
len = rc.cols;
if (TES_PASSWORD & style)
{
if (edit->showpass == TW_SHOW)
{
memset(buf, edit->passchar, len);
}
else
{
memset(buf, ' ', len);
}
buf[len] = 0;
TuiDrawText(dc, rc.y, rc.x, buf, attrs);
return;
}
if (TuiIsWndVisible(wnd))
{
len = MIN(strlen(edit->editbuf), rc.cols);
memset(buf, 0, TUI_MAX_WNDTEXT);
memcpy(buf, &edit->editbuf[edit->firstchar], len);
if (edit->editing)
{
TuiPrintTextAlignment(text, buf, rc.cols, ALIGN_LEFT);
}
else
{
TuiPrintTextAlignment(text, buf, rc.cols, style);
}
TuiDrawText(dc, rc.y, rc.x, text, attrs);
}
TuiMoveYX(dc, rc.y, rc.x);
}
VOID TEDT_OnLimitText(TWND wnd, INT limit)
{
TEDIT edit = 0;
CHAR text[TUI_MAX_WNDTEXT + 1];
if (limit > 0 || limit <= TUI_MAX_WNDTEXT)
{
edit = (TEDIT)TuiGetWndParam(wnd);
edit->limitchars = limit;
TuiGetWndText(wnd, text, TUI_MAX_WNDTEXT);
if (strlen(text) > limit)
{
text[limit] = 0;
TuiSetWndText(wnd, text);
strcpy(edit->editbuf, text);
}
}
}
VOID TEDT_OnSetPasswdChar(TWND wnd, CHAR passchar)
{
TEDIT edit = 0;
edit = (TEDIT)TuiGetWndParam(wnd);
edit->passchar = passchar;
}
VOID TEDT_OnShowPasswdChar(TWND wnd, INT show)
{
TEDIT edit = 0;
edit = (TEDIT)TuiGetWndParam(wnd);
edit->showpass = (show == TW_SHOW ? TW_SHOW : TW_HIDE);
}
VOID TEDT_OnSetDecWidth(TWND wnd, INT width)
{
TEDIT edit = 0;
edit = (TEDIT)TuiGetWndParam(wnd);
edit->decwidth = width;
}
LONG EDITPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_CREATE:
{
return TEDT_OnCreate(wnd);
}
case TWM_DESTROY:
{
TEDT_OnDestroy(wnd);
return 0;
}
case TWM_SETFOCUS:
{
TEDT_OnSetFocus(wnd);
break;
}
case TWM_KILLFOCUS:
{
return TEDT_OnKillFocus(wnd);
}
case TWM_CHAR:
{
TEDT_OnChar(wnd, (LONG)wparam);
break;
}
case TWM_PAINT:
{
TEDT_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
case TEM_LIMITTEXT:
{
TEDT_OnLimitText(wnd, (INT)wparam);
return 0;
}
case TEM_SETPASSWDCHAR:
{
TEDT_OnSetPasswdChar(wnd, (CHAR)wparam);
return 0;
}
case TEM_SETDECWIDTH:
{
TEDT_OnSetDecWidth(wnd, (INT)wparam);
return 0;
}
case TEM_SHOWPASSWDCHAR:
{
TEDT_OnShowPasswdChar(wnd, (INT)wparam);
return 0;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
/*-------------------------------------------------------------------
* File name: tlb.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* LISTBOX functions
*-----------------------------------------------------------------*/
struct _TLISTBOXITEMSTRUCT
{
CHAR itemtext[TUI_MAX_WNDTEXT+1];
LPVOID data;
INT checked;
struct _TLISTBOXITEMSTRUCT *prev;
struct _TLISTBOXITEMSTRUCT *next;
};
typedef struct _TLISTBOXITEMSTRUCT tlistbox_t;
struct _TUILISTBOXSTRUCT
{
INT firstvisible;
INT nitems; /* item counts */
INT cursel; /* highlight item */
tlistbox_t* firstitem; /* always be item id = 0 if it is existing */
tlistbox_t* lastitem;
tlistbox_t* selitem; /* must be the same cursel item */
tlistbox_t* firstvisibleitem;
INT checkeditems; /* count item checked */
tlistbox_t* lastitemchecked; /* to identify the last item checked */
};
typedef struct _TUILISTBOXSTRUCT _TLISTBOX;
typedef struct _TUILISTBOXSTRUCT *TLISTBOX;
tlistbox_t* _TLB_FindItemByIndex(TWND wnd, INT idx);
INT TLB_OnCountItemCheck(TWND wnd);
INT TLB_OnGetItemChecked(TWND wnd, INT idx);
INT TLB_OnSetItemChecked(TWND wnd, INT idx, INT check);
LPVOID TLB_OnGetItemData(TWND wnd, INT idx);
VOID TLB_OnSetItemData(TWND wnd, INT idx, LPVOID data);
VOID TLB_OnSetCurSel(TWND wnd, INT idx);
LONG TLB_OnGetItemCount(TWND wnd);
VOID TLB_OnSetItemText(TWND wnd, INT idx, LPSTR text);
LONG TLB_OnGetItemText(TWND wnd, INT idx, LPSTR text);
INT TLB_OnGetCurSel(TWND wnd);
VOID TLB_OnDeleteAllItems(TWND wnd);
VOID TLB_OnDeleteItem(TWND wnd, LONG idx);
LONG TLB_OnAddItem(TWND wnd, LPCSTR text);
VOID TLB_OnPaint(TWND wnd, TDC dc);
VOID TLB_OnKeyDown(TWND wnd, LONG ch);
LONG TLB_OnKillFocus(TWND wnd);
VOID TLB_OnSetFocus(TWND wnd);
VOID TLB_OnDestroy(TWND wnd);
LONG TLB_OnCreate(TWND wnd);
LONG LISTBOXPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
tlistbox_t* _TLB_FindItemByIndex(TWND wnd, INT idx)
{
TLISTBOX lb = 0;
INT i = 0;
tlistbox_t* item = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
if (idx < 0 || idx >= lb->nitems)
{
return 0;
}
item = lb->firstitem;
for (i = 0; i < lb->nitems && item; ++i, item = item->next)
{
if (i == idx)
{
return item;
}
}
return 0;
}
LONG TLB_OnCreate(TWND wnd)
{
TLISTBOX lb = 0;
/* initial memory for static control */
lb = (TLISTBOX)malloc(sizeof(_TLISTBOX));
if (!lb)
{
return TUI_ERROR;
}
lb->firstvisible = -1;
lb->cursel = -1;
lb->nitems = 0;
lb->firstitem = 0;
lb->lastitem = 0;
lb->selitem = 0;
lb->firstvisibleitem = 0;
lb->checkeditems = 0;
lb->lastitemchecked = 0;
TuiSetWndParam(wnd, (LPVOID)lb);
#ifdef __USE_CURSES__
TuiSetWndTextAttrs(wnd, COLOR_PAIR(YELLOW_BLUE));
#elif defined __USE_QIO__
TuiSetWndTextAttrs(wnd, YELLOW_BLUE);
#endif
return TUI_CONTINUE;
}
VOID TLB_OnDestroy(TWND wnd)
{
TLISTBOX lb = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
/* release memory of static control */
TLB_DeleteAllItems(wnd);
free(lb);
}
VOID TLB_OnSetFocus(TWND wnd)
{
TLISTBOX lb = 0;
NMHDR nmhdr;
lb = (TLISTBOX)TuiGetWndParam(wnd);
if (lb->cursel >= lb->nitems)
{
lb->cursel = 0;
}
else if (lb->cursel < 0)
{
lb->cursel = 0;
}
TuiInvalidateWnd(wnd);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TLBN_SETFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
}
LONG TLB_OnKillFocus(TWND wnd)
{
NMHDR nmhdr;
LONG rc = TUI_CONTINUE;
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TLBN_KILLFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
return rc;
}
VOID TLB_OnKeyDown(TWND wnd, LONG ch)
{
TLISTBOX lb = 0;
NMHDR nmhdr;
INT repaint = 0;
DWORD style = TuiGetWndStyle(wnd);
INT lines = 0;
RECT rc;
lb = (TLISTBOX)TuiGetWndParam(wnd);
TuiGetWndRect(wnd, &rc);
switch (ch)
{
case TVK_SPACE:
{
if ((style & TLBS_CHECKBOX) ||
(style & TLBS_RADIOBOX))
{
/* get current and check it */
TLB_SetItemChecked(wnd, lb->cursel, LB_CHECKED);
}
++repaint;
break;
}
case KEY_DOWN:
case KEY_RIGHT:
{
++lines;
++repaint;
break;
}
case KEY_UP:
case KEY_LEFT:
{
--lines;
++repaint;
break;
}
case TVK_PRIOR:
#ifdef __USE_CURSES__
case KEY_PPAGE:
#elif (defined __USE_QIO__ && defined __VMS__)
case KEY_PREV:
#endif
{
lines -= rc.lines;
++repaint;
break;
}
case TVK_NEXT:
#ifdef __USE_CURSES__
case KEY_NPAGE:
#elif (defined __USE_QIO__ && defined __VMS__)
case KEY_NEXT:
#endif
{
lines += rc.lines;
++repaint;
break;
}
}
if (repaint)
{
lb->cursel += lines;
if (lb->cursel >= lb->nitems)
{
lb->cursel = lb->nitems - 1;
}
else if (lb->cursel < 0)
{
lb->cursel = 0;
}
/* find the new first visible */
if (lb->cursel >= lb->firstvisible + rc.lines)
{
lb->firstvisible += lines;
if (lb->firstvisible > lb->nitems - rc.lines)
{
lb->firstvisible = lb->nitems - rc.lines;
}
}
else if (lb->firstvisible > lb->cursel)
{
lb->firstvisible += lines;
if (lb->firstvisible < 0)
{
lb->firstvisible = 0;
}
}
TuiInvalidateWnd(wnd);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TLBN_SELCHANGED;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
}
lb->selitem = _TLB_FindItemByIndex(wnd, lb->cursel);
lb->firstvisibleitem = _TLB_FindItemByIndex(wnd, lb->firstvisible);
}
VOID TLB_OnPaint(TWND wnd, TDC dc)
{
TLISTBOX lb = 0;
INT i = 0;
tlistbox_t* item = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
CHAR text[TUI_MAX_WNDTEXT+1];
DWORD attrs = TuiGetWndTextAttrs(wnd);
DRAWITEM di;
RECT rc;
DWORD style = TuiGetWndStyle(wnd);
if (!TuiIsWndVisible(wnd))
{
return;
}
lb = (TLISTBOX)TuiGetWndParam(wnd);
/* draw */
if (lb->nitems > 0)
{
item = lb->firstitem;
TuiGetWndRect(wnd, &rc);
for (i = 0; i < lb->nitems && item; ++i, item = item->next)
{
if (i < lb->firstvisible)
{
/* do nothing */
continue;
}
else if (i - lb->firstvisible < rc.lines)
{
if (style & TLBS_OWNERDRAW)
{
memset(&di, 0, sizeof(DRAWITEM));
di.rcitem.y = rc.y + (i - lb->firstvisible);
di.rcitem.x = rc.x;
di.rcitem.lines = 1;
di.rcitem.cols = rc.cols;
di.idx = i;
TuiSendMsg(TuiGetParent(wnd), TWM_DRAWITEM, (WPARAM)i, (LPARAM)&di);
}
else
{
strcpy(text, "");
if (style & TLBS_CHECKBOX)
{
if (item->checked)
{
strcpy(text, "[X] ");
}
else
{
strcpy(text, "[ ] ");
}
}
else if (style & TLBS_RADIOBOX)
{
if (item->checked)
{
strcpy(text, "(*) ");
}
else
{
strcpy(text, "( ) ");
}
}
/* copy from item text */
strcat(text, item->itemtext);
TuiPrintTextAlignment(buf, text, rc.cols, style);
TuiDrawText(dc,
rc.y+(i-lb->firstvisible),
rc.x,
buf,
#ifdef __USE_CURSES__
(i == lb->cursel ? A_REVERSE|attrs : attrs));
#elif defined __USE_QIO__
0); /* highlight */
#endif
}
}/* not owner draw */
} /* for each item */
} /* items are valid */
}
LONG TLB_OnAddItem(TWND wnd, LPCSTR text)
{
TLISTBOX lb = 0;
LONG len = 0;
tlistbox_t* item = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
item = (tlistbox_t*)malloc(sizeof(tlistbox_t));
if (item)
{
memset(item, 0, sizeof(tlistbox_t));
len = strlen(text);
if (len > TUI_MAX_WNDTEXT)
{
len = TUI_MAX_WNDTEXT;
}
strncpy(item->itemtext, text, len);
if (lb->firstitem)
{
item->prev = lb->lastitem;
lb->lastitem->next = item;
lb->lastitem = item;
}
else
{
lb->firstitem = lb->lastitem = item;
lb->firstvisible = 0;
}
++lb->nitems;
return lb->nitems;
}
return TUI_MEM;
}
VOID TLB_OnDeleteItem(TWND wnd, LONG idx)
{
TLISTBOX lb = 0;
tlistbox_t* item = 0;
tlistbox_t* nextitem = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
/* remove the links */
nextitem = item->next;
if (nextitem)
{
nextitem->prev = item->prev;
}
if (item->prev)
{
item->prev->next = nextitem;
}
/* check if removed item is the first item or the last item */
if (item == lb->firstitem)
{
lb->firstitem = nextitem;
}
else if (item == lb->lastitem)
{
lb->lastitem = item->prev;
}
/* free the memory */
item->next = item->prev = 0;
free(item);
/* decrement items */
--lb->nitems;
if (lb->cursel >= lb->nitems)
{
lb->cursel = lb->nitems - 1;
}
}
}
VOID TLB_OnDeleteAllItems(TWND wnd)
{
TLISTBOX lb = 0;
INT nitems = 0;
INT i = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
nitems = lb->nitems;
for (i = 0; i < nitems; ++i)
{
TuiPostMsg(wnd, TLBM_DELETEITEM, 0, 0);
}
}
INT TLB_OnGetCurSel(TWND wnd)
{
TLISTBOX lb = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
return lb->cursel;
}
LONG TLB_OnGetItemText(TWND wnd, INT idx, LPSTR text)
{
tlistbox_t* item = 0;
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
strcpy(text, item->itemtext);
}
return strlen(text);
}
VOID TLB_OnSetItemText(TWND wnd, INT idx, LPSTR text)
{
tlistbox_t* item = 0;
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
strcpy(item->itemtext, text);
}
}
LONG TLB_OnGetItemCount(TWND wnd)
{
TLISTBOX lb = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
return lb->nitems;
}
VOID TLB_OnSetCurSel(TWND wnd, INT idx)
{
TLISTBOX lb = 0;
NMHDR nmhdr;
RECT rc;
lb = (TLISTBOX)TuiGetWndParam(wnd);
if (idx < 0 || idx >= lb->nitems)
{
idx = -1;
}
lb->cursel = idx;
if (lb->cursel >= 0)
{
lb->firstvisible = lb->cursel;
TuiGetWndRect(wnd, &rc);
if (lb->firstvisible + rc.lines > lb->nitems)
{
lb->firstvisible = lb->nitems - rc.lines;
}
}
else
{
lb->firstvisible = 0;
}
TuiInvalidateWnd(wnd);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TLBN_SELCHANGED;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
lb->selitem = _TLB_FindItemByIndex(wnd, lb->cursel);
lb->firstvisibleitem = _TLB_FindItemByIndex(wnd, lb->firstvisible);
}
VOID TLB_OnSetItemData(TWND wnd, INT idx, LPVOID data)
{
tlistbox_t* item = 0;
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
item->data = data;
}
}
LPVOID TLB_OnGetItemData(TWND wnd, INT idx)
{
tlistbox_t* item = 0;
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
return item->data;
}
return 0;
}
INT TLB_OnSetItemChecked(TWND wnd, INT idx, INT check)
{
tlistbox_t* item = 0;
TLISTBOX lb = 0;
DWORD style = TuiGetWndStyle(wnd);
lb = (TLISTBOX)TuiGetWndParam(wnd);
item = _TLB_FindItemByIndex(wnd, idx);
/* found and do the check item state */
if (item)
{
if (check == LB_UNCHECKED)
{
--lb->checkeditems;
if (lb->checkeditems < 0)
{
lb->checkeditems = 0;
lb->lastitemchecked = 0;
}
item->checked = LB_UNCHECKED;
}
else
{
/* unselected the last if it is radio style */
if (style & TLBS_RADIOBOX)
{
if (lb->lastitemchecked)
{
lb->lastitemchecked->checked = LB_UNCHECKED;
}
}
else if (style & TLBS_CHECKBOX)
{
if (item->checked == LB_CHECKED)
{
--lb->checkeditems;
if (lb->checkeditems < 0)
{
lb->checkeditems = 0;
lb->lastitemchecked = 0;
}
item->checked = LB_UNCHECKED;
return LB_OK;
}
}
/* count checked item */
++lb->checkeditems;
if (lb->checkeditems > lb->nitems)
{
lb->checkeditems = lb->nitems;
}
/* checked and save the last checked item */
item->checked = LB_CHECKED;
lb->lastitemchecked = item;
}
return LB_OK;
}
return LB_ERROR;
}
INT TLB_OnGetItemChecked(TWND wnd, INT idx)
{
tlistbox_t* item = 0;
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
return item->checked;
}
return LB_ERROR;
}
INT TLB_OnCountItemCheck(TWND wnd)
{
TLISTBOX lb = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
return lb->checkeditems;
}
LONG LISTBOXPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TLBM_COUNTITEMCHECKED:
{
return TLB_OnCountItemCheck(wnd);
}
case TLBM_GETITEMCHECKED:
{
return TLB_OnGetItemChecked(wnd, (INT)wparam);
}
case TLBM_SETITEMCHECKED:
{
return TLB_OnSetItemChecked(wnd, (INT)wparam, (INT)lparam);
}
case TWM_CREATE:
{
return TLB_OnCreate(wnd);
}
case TWM_DESTROY:
{
TLB_OnDestroy(wnd);
return 0;
}
case TWM_SETFOCUS:
{
TLB_OnSetFocus(wnd);
break;
}
case TWM_KILLFOCUS:
{
return TLB_OnKillFocus(wnd);
}
case TWM_KEYDOWN:
{
TLB_OnKeyDown(wnd, (LONG)wparam);
break;
}
case TWM_PAINT:
{
TLB_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
case TLBM_ADDITEM:
{
return TLB_OnAddItem(wnd, (LPCSTR)lparam);
}
case TLBM_DELETEITEM:
{
TLB_OnDeleteItem(wnd, (LONG)wparam);
return 0;
}
case TLBM_GETCURSEL:
{
return TLB_OnGetCurSel(wnd);
}
case TLBM_SETCURSEL:
{
TLB_OnSetCurSel(wnd, (INT)wparam);
return 0;
}
case TLBM_DELETEALLITEMS:
{
TLB_OnDeleteAllItems(wnd);
return 0;
}
case TLBM_GETITEMCOUNT:
{
return TLB_OnGetItemCount(wnd);
}
case TLBM_SETITEMDATA:
{
TLB_OnSetItemData(wnd, (INT)wparam, (LPVOID)lparam);
return 0;
}
case TLBM_GETITEMDATA:
{
return (LONG)TLB_OnGetItemData(wnd, (INT)wparam);
}
case TLBM_SETITEMTEXT:
{
TLB_OnSetItemText(wnd, (INT)wparam, (LPSTR)lparam);
return 0;
}
case TLBM_GETITEMTEXT:
{
return TLB_OnGetItemText(wnd, (INT)wparam, (LPSTR)lparam);
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
/*-------------------------------------------------------------------
* File name: tlctl.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* LISTCTRL functions
*-----------------------------------------------------------------*/
struct _TLISTCELLSTRUCT
{
INT y;
INT x;
CHAR caption[TUI_MAX_WNDTEXT+1];
DWORD attrs;
VOID* data;
struct _TLISTCELLSTRUCT *prev;
struct _TLISTCELLSTRUCT *next;
};
typedef struct _TLISTCELLSTRUCT tlistcell_t;
struct _THEADERSTRUCT
{
INT id;
CHAR caption[TUI_MAX_WNDTEXT+1];
INT cols; /* width */
INT align; /* left is a default */
DWORD attrs;
tlistcell_t* firstcell;
tlistcell_t* lastcell;
struct _THEADERSTRUCT *prev;
struct _THEADERSTRUCT *next;
};
typedef struct _THEADERSTRUCT theader_t;
struct _TLISTCTRLSTRUCT
{
theader_t* firsthdr;
theader_t* lasthdr;
theader_t* firstvisiblehdr;
theader_t* lastvisiblehdr;
INT nheaders;
INT nitems;
INT hdrids; /* header id */
INT hdrallwidths;
/* item control */
INT curselrow;
INT curselcol;
INT firstvisibleitem;
TWND editbox;
};
typedef struct _TLISTCTRLSTRUCT _TLISTCTRL;
typedef struct _TLISTCTRLSTRUCT *TLISTCTRL;
theader_t* _TLCTL_FindHeaderByIndex(TLISTCTRL lctl, INT col);
tlistcell_t* _TLCTL_FindCellByIndex(TLISTCTRL lctl, INT col, INT idx);
tlistcell_t* _TLCTL_FindCellByHeader(TLISTCTRL lctl, theader_t* header, INT idx);
LONG _TLCTL_GetCellRect(TLISTCTRL lctl, INT col, INT idx, RECT* rect);
LONG LISTCTRLPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
VOID TLCTL_OnKeyDown(TWND wnd, LONG ch);
VOID TLCTL_OnPaint(TWND wnd, TDC dc);
LONG TLCTL_OnAddItem(TWND wnd, LPSTR text, INT nitems);
VOID TLCTL_OnDeleteAllItems(TWND wnd);
VOID TLCTL_OnDeleteColumn(TWND wnd, INT col);
LONG TLCTL_OnAddColumn(TWND wnd, HEADERITEM* hdritem);
VOID TLCTL_OnDestroy(TWND wnd);
LONG TLCTL_OnCreate(TWND wnd);
LONG TLCTL_OnGetItem(TWND wnd, UINT flags, SUBITEM* subitem);
LONG TLCTL_OnSetItem(TWND wnd, UINT flags, SUBITEM* subitem);
theader_t* _TLCTL_FindHeaderByIndex(TLISTCTRL lctl, INT col)
{
theader_t* header = 0;
INT i;
if (col < 0 || col >= lctl->nheaders)
{
return 0; /* no header deleted */
}
header = lctl->firsthdr;
for (i = 0; i == col && i < lctl->nheaders; ++i)
{
header = header->next;
}
return header;
}
tlistcell_t* _TLCTL_FindCellByIndex(TLISTCTRL lctl, INT col, INT idx)
{
tlistcell_t* cell = 0;
theader_t* header = 0;
INT i;
if (idx < 0 || idx >= lctl->nitems)
{
return 0;
}
header = _TLCTL_FindHeaderByIndex(lctl, col);
if (header)
{
cell = header->firstcell;
for (i = 0; i == idx && i < lctl->nitems; ++i)
{
cell = cell->next;
}
}
return cell;
}
tlistcell_t* _TLCTL_FindCellByHeader(TLISTCTRL lctl, theader_t* header, INT idx)
{
tlistcell_t* cell = 0;
INT i;
if (idx < 0 || idx >= lctl->nitems)
{
return 0;
}
if (header)
{
cell = header->firstcell;
for (i = 0; i == idx && i < lctl->nitems; ++i)
{
cell = cell->next;
}
}
return cell;
}
LONG _TLCTL_GetCellRect(TLISTCTRL lctl, INT col, INT idx, RECT* rect)
{
/*
tlistcell_t* cell = 0;
TLISTCTRL lctl = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
cell = TLCTL_FindCellByIndex(wnd, row, col);
*/
return TUI_OK;
}
LONG TLCTL_OnCreate(TWND wnd)
{
TLISTCTRL lctl = (TLISTCTRL)malloc(sizeof(_TLISTCTRL));
if (!lctl)
{
return TUI_MEM;
}
memset(lctl, 0, sizeof(_TLISTCTRL));
lctl->hdrids = 1;
lctl->editbox = TuiCreateWnd(EDIT,
"",
TWS_CHILD|TES_AUTOHSCROLL,
0, /* y */
0, /* x */
1, /* lines */
1, /* cols */
wnd, /* parent */
lctl->hdrids, /* id */
0); /* no parameter */
if (!lctl->editbox)
{
free(lctl);
return TUI_MEM;
}
lctl->curselrow = -1;
lctl->curselcol = -1;
lctl->firstvisibleitem = -1;
/* increment child ids */
++lctl->hdrids;
/* save memory */
TuiSetWndParam(wnd, (LPVOID)lctl);
return TUI_CONTINUE;
}
VOID TLCTL_OnDestroy(TWND wnd)
{
TLISTCTRL lctl = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
TLC_DeleteAllColumns(wnd);
free(lctl);
}
LONG TLCTL_OnAddColumn(TWND wnd, HEADERITEM* hdritem)
{
TLISTCTRL lctl = 0;
theader_t* header = 0;
RECT rc;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
if (lctl->nitems > 0)
{
/* not allowed to add header after there are any items */
return TUI_ERROR;
}
header = (theader_t*)malloc(sizeof(theader_t));
if (!header)
{
return TUI_MEM;
}
memset(header, 0, sizeof(theader_t));
TuiGetWndRect(TuiGetParent(wnd), &rc);
/*header->caption = hdritem->caption;*/
strncpy(header->caption,
hdritem->caption,
MIN(TUI_MAX_WNDTEXT, strlen(hdritem->caption)));
header->cols = hdritem->cols;
header->align = hdritem->align;
header->attrs = hdritem->attrs;
header->id = lctl->hdrids;
/* make link */
if (lctl->firsthdr)
{
header->prev = lctl->lasthdr;
lctl->lasthdr->next = header;
lctl->lasthdr = header;
}
else
{
lctl->firsthdr = lctl->lasthdr = header;
lctl->firstvisiblehdr = header;
}
/* increment child ids */
++lctl->hdrids;
++lctl->nheaders;
lctl->hdrallwidths += header->cols;
return 0;
}
VOID TLCTL_OnDeleteColumn(TWND wnd, INT col)
{
TLISTCTRL lctl = 0;
theader_t* next = 0;
tlistcell_t* cell = 0;
tlistcell_t* nextcell = 0;
theader_t* header = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
header = _TLCTL_FindHeaderByIndex(lctl, col);
if (!header)
{
return;
}
/* re-link */
next = header->next;
if (next)
{
next->prev = header->prev;
}
if (header->prev)
{
header->prev->next = next;
}
if (header == lctl->firsthdr)
{
lctl->firsthdr = next;
}
else if (header == lctl->lasthdr)
{
lctl->lasthdr = header->prev;
}
/* delete */
header->next = header->prev = 0;
cell = header->firstcell;
while (cell)
{
nextcell = cell->next;
/*free(cell->caption);*/
cell->next = cell->prev = 0;
free(cell);
cell = nextcell;
}
free(header);
/* done */
--lctl->nheaders;
}
VOID TLCTL_OnDeleteAllItems(TWND wnd)
{
INT nitems = 0;
INT i = 0;
TLISTCTRL lctl = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
nitems = lctl->nheaders;
for (i = 0; i < nitems; ++i)
{
TuiSendMsg(wnd, TLCM_DELETEITEM, 0, 0);
}
}
VOID TLC_OnDeleteItem(TWND wnd, INT idx)
{
TLISTCTRL lctl = 0;
tlistcell_t* cell = 0;
tlistcell_t* nextcell = 0;
theader_t* header = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
if (lctl->nitems <= 0 || idx < 0 || idx >= lctl->nitems)
{
return;
}
header = lctl->firsthdr;
while (header)
{
cell = _TLCTL_FindCellByHeader(lctl, header, idx);
nextcell = cell->next;
if (nextcell)
{
nextcell->prev = cell->prev;
}
if (cell->prev)
{
cell->prev->next = nextcell;
}
if (header->firstcell == cell)
{
header->firstcell = cell->next;
}
else if (header->lastcell == cell)
{
header->lastcell = cell->prev;
}
cell->next = cell->prev = 0;
/*free(cell->caption);*/
free(cell);
/* next header */
header = header->next;
}
--lctl->nitems;
}
LONG TLCTL_OnAddItem(TWND wnd, LPSTR text, INT nitems)
{
TLISTCTRL lctl = 0;
INT i = 0;
CHAR* tok;
theader_t* header = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
tlistcell_t* newcell = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
if (lctl->nheaders > 0)
{
/* insert into all listboxes */
header = lctl->firsthdr;
strcpy(buf, text);
tok = strtok(buf, "\t");
while (tok && i < nitems && i < lctl->nheaders)
{
newcell = (tlistcell_t*)malloc(sizeof(tlistcell_t));
if (!newcell)
{
break;
}
memset(newcell, 0, sizeof(tlistcell_t));
/*newcell->caption = (CHAR*)malloc(TUI_MAX_WNDTEXT+1);*/
strncpy(newcell->caption, tok, MIN(TUI_MAX_WNDTEXT, strlen(tok)));
/* add the new item */
if (header->firstcell)
{
newcell->prev = header->lastcell;
header->lastcell->next = newcell;
header->lastcell = newcell;
}
else
{
header->firstcell = header->lastcell = newcell;
lctl->firstvisibleitem = 0;
}
/* insert next */
header = header->next;
tok = strtok(0, "\t");
++i;
}
/* all items count */
++lctl->nitems;
} /* have header */
return lctl->nitems;
}
VOID TLCTL_OnPaint(TWND wnd, TDC dc)
{
TLISTCTRL lctl = 0;
theader_t* header = 0;
INT width = 0;
RECT rcitem, rc, rccell;
CHAR buf[TUI_MAX_WNDTEXT+1];
DWORD attrs = 0;
LONG len = 0;
tlistcell_t* visiblecell = 0;
INT i = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
if (lctl->nheaders <= 0 || !TuiIsWndVisible(wnd))
{
return;
}
/* draw headers */
TuiGetWndRect(wnd, &rc);
rcitem = rc; /* copy some values */
header = lctl->firstvisiblehdr;
width = header->cols;
if (width > rc.cols)
{
width = rc.cols;
}
while (header && width < rc.cols)
{
rcitem.cols = header->cols;
rcitem.x = rc.x + width - rcitem.cols;
attrs = header->attrs;
#ifdef __USE_CURSES__
attrs |= A_REVERSE;
#elif defined __USE_QIO__
attrs = 0;
#endif
len = TuiPrintTextAlignment(buf,
header->caption,
rcitem.cols,
ALIGN_CENTER);
buf[0] = '[';
buf[len-1] = ']';
TuiDrawText(dc,
rcitem.y,
rcitem.x,
buf,
attrs);
/* draw cells */
rccell = rcitem;
rccell.y += 1;
visiblecell = header->firstcell;
for (i = 0; i < lctl->nitems && visiblecell; ++i, visiblecell = visiblecell->next)
{
if (i < lctl->firstvisibleitem)
{
/* do nothing */
continue;
}
else if (i - lctl->firstvisibleitem <= rc.lines - 2)
{
len = TuiPrintTextAlignment(buf,
visiblecell->caption,
header->cols,
header->align);
attrs = visiblecell->attrs;
#ifdef __USE_CURSES__
if (i == lctl->curselrow)
{
attrs |= A_REVERSE;
}
#elif defined __USE_QIO__
#endif
TuiDrawText(dc,
rccell.y,
rccell.x,
buf,
attrs);
++rccell.y;
}
} /* for each drawing cell */
/* draw next header */
header = header->next;
if (header)
{
width += header->cols;
if (width > rc.cols)
{
break;
}
}
} /* while header */
/* print arrow controls */
#ifdef __USE_CURSES__
attrs |= A_REVERSE;
#elif defined __USE_QIO__
attrs = 0;
#endif
if (lctl->firsthdr != lctl->firstvisiblehdr)
{
TuiPutChar(dc, rc.y, rc.x, '<', attrs);
}
/* save the last visible */
if (header)
{
lctl->lastvisiblehdr = header->prev;
TuiPutChar(dc, rc.y, rc.x + width - header->cols - 1, '>', attrs);
}
else
{
lctl->lastvisiblehdr = lctl->lasthdr;
}
TuiMoveYX(dc, rcitem.y,
rcitem.x);
}
VOID TLCTL_OnKeyDown(TWND wnd, LONG ch)
{
TLISTCTRL lctl = 0;
INT repaint = 1;
RECT rc;
INT lines = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
TuiGetWndRect(wnd, &rc);
if (lctl->nheaders <= 0)
{
return;
}
switch (ch)
{
case TVK_SPACE:
{
/*repaint = 1;*/
break;
}
case KEY_RIGHT:
{
if (lctl->lastvisiblehdr != lctl->lasthdr)
{
lctl->firstvisiblehdr = lctl->firstvisiblehdr->next;
++repaint;
}
break;
}
case KEY_LEFT:
{
if (lctl->firstvisiblehdr != lctl->firsthdr)
{
lctl->firstvisiblehdr = lctl->firstvisiblehdr->prev;
++repaint;
}
break;
}
case KEY_DOWN:
{
++lines;
++repaint;
break;
}
case KEY_UP:
{
--lines;
++repaint;
break;
}
case TVK_PRIOR:
#ifdef __USE_CURSES__
case KEY_PPAGE:
#elif (defined __USE_QIO__ && defined __VMS__)
case KEY_PREV:
#endif
{
lines -= rc.lines - 1;
++repaint;
break;
}
case TVK_NEXT:
#ifdef __USE_CURSES__
case KEY_NPAGE:
#elif (defined __USE_QIO__ && defined __VMS__)
case KEY_NEXT:
#endif
{
lines += rc.lines - 1;
++repaint;
break;
}
}
if (repaint)
{
lctl->curselrow += lines;
if (lctl->curselrow >= lctl->nitems)
{
lctl->curselrow = lctl->nitems - 1;
}
else if (lctl->curselrow < 0)
{
lctl->curselrow = 0;
}
if (lctl->curselrow >= lctl->firstvisibleitem + rc.lines - 1)
{
lctl->firstvisibleitem += lines;
if (lctl->firstvisibleitem - 1 > lctl->nitems - rc.lines)
{
lctl->firstvisibleitem = lctl->nitems - rc.lines;
}
}
else if (lctl->firstvisibleitem > lctl->curselrow)
{
lctl->firstvisibleitem += lines;
if (lctl->firstvisibleitem < 0)
{
lctl->firstvisibleitem = 0;
}
}
TuiInvalidateWnd(wnd);
/* send notification */
/*
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TLBN_SELCHANGED;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
*/
}
}
LONG TLCM_OnGetItemCount(TWND wnd)
{
TLISTCTRL lctl = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
return lctl->nitems;
}
LONG TLCTL_OnSetItem(TWND wnd, UINT flags, SUBITEM* subitem)
{
TLISTCTRL lctl = 0;
tlistcell_t* cell = 0;
LONG rc = TUI_ERROR;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
cell = _TLCTL_FindCellByIndex(lctl, subitem->col, subitem->idx);
if (cell)
{
if (flags & LCFM_TEXT) { strcpy(cell->caption, subitem->text); }
if (flags & LCFM_DATA) { cell->data = subitem->data; }
if (flags & LCFM_ATTRS) { cell->attrs = subitem->attrs; }
rc = TUI_OK;
}
return rc;
}
LONG TLCTL_OnGetItem(TWND wnd, UINT flags, SUBITEM* subitem)
{
TLISTCTRL lctl = 0;
tlistcell_t* cell = 0;
LONG rc = TUI_ERROR;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
cell = _TLCTL_FindCellByIndex(lctl, subitem->col, subitem->idx);
if (cell)
{
if (flags & LCFM_TEXT) { subitem->text = cell->caption; }
if (flags & LCFM_DATA) { subitem->data = cell->data; }
if (flags & LCFM_ATTRS) { subitem->attrs = cell->attrs; }
rc = TUI_OK;
}
return rc;
}
LONG LISTCTRLPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_CREATE:
{
/* initial memory for static control */
return TLCTL_OnCreate(wnd);
}
case TWM_DESTROY:
{
/* release memory of static control */
TLCTL_OnDestroy(wnd);
return 0;
}
/*
case TWM_SETFOCUS:
{
TLCTL_OnSetFocus(wnd);
break;
}
case TWM_KILLFOCUS:
{
return TLCTL_OnKillFocus(wnd);
}
*/
case TWM_KEYDOWN:
{
TLCTL_OnKeyDown(wnd, (LONG)wparam);
break;
}
case TWM_PAINT:
{
TLCTL_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
case TLCM_ADDCOLUMN:
{
return TLCTL_OnAddColumn(wnd, (HEADERITEM*)lparam);
}
case TLCM_DELETECOLUMN:
{
TLCTL_OnDeleteColumn(wnd, (INT)wparam);
return 0;
}
case TLCM_DELETEALLCOLUMNS:
{
TLCTL_OnDeleteAllItems(wnd);
return 0;
}
case TLCM_ADDITEM:
{
return TLCTL_OnAddItem(wnd, (LPSTR)lparam, (INT)wparam);
}
case TLCM_DELETEITEM:
{
TLC_OnDeleteItem(wnd, (INT)wparam);
return 0;
}
case TLCM_DELETEALLITEMS:
{
TLCTL_OnDeleteAllItems(wnd);
return 0;
}
case TLCM_SETITEM:
{
return TLCTL_OnSetItem(wnd, (UINT)wparam, (SUBITEM*)lparam);
}
case TLCM_GETITEM:
{
return TLCTL_OnGetItem(wnd, (UINT)wparam, (SUBITEM*)lparam);
}
case TLCM_GETITEMCOUNT:
{
return TLCM_OnGetItemCount(wnd);
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
/*-------------------------------------------------------------------
* File name: tui_test.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curses.h>
#include "tui.h"
#define IDC_STATUSBAR 199
#define IDC_NAME 200
#define IDC_LISTBOX1 204
#define IDC_PASSWORD 205
#define IDC_OK 206
#define IDC_CANCEL 207
#define IDC_LISTBOX2 208
#define IDC_LISTBOX3 209
#define IDC_CLOSE 210
#define IDC_SAVE 211
#define IDC_OPENDLG2 212
#define IDC_OPENDLG3 213
#define IDC_MSG 214
#define IDC_PRICE 215
WNDTEMPL dlg1[] =
{
/* 1st object is always dialog */
{ "mywndproc", "Dialog1", 1, 0, 0, 25, 80, TWS_WINDOW, 0 },
/* 2nd and others are controls */
{ STATIC, "Name:", 100, 1, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "12345678901234567890", IDC_NAME, 1, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|
TES_LEFT|TES_APPENDMODE|TES_UPPERCASE|TES_AUTOHSCROLL, 0 },
{ STATIC, "ID:", 101, 2, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "DT66234", 201, 2, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|
TES_CENTER|TES_AUTOHSCROLL, 0 },
{ STATIC, "Tel:", 102, 3, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "1234", 202, 3, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|
TES_NUMBER|TES_RIGHT|TES_AUTOHSCROLL, 0 },
{ STATIC, "Email:", 103, 4, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "abc@abc.com", 203, 4, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|TWS_DISABLED|
TES_AUTOHSCROLL, 0 },
{ STATIC, "Password:", 104, 5, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "welcome1!", IDC_PASSWORD, 5, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|
TES_LEFT|TES_PASSWORD|TES_AUTOHSCROLL, 0 },
{ STATIC, "Price:", 105, 6, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "399.50", IDC_PRICE, 6, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|
TES_RIGHT|TES_DECIMAL|TES_AUTOHSCROLL, 0 },
{ LISTBOX,"", IDC_LISTBOX1, 8, 1, 5, 16, TWS_CHILD|TWS_VISIBLE|TLBS_CENTER, 0 },
{ LISTBOX,"", IDC_LISTBOX2, 8, 21, 5, 16,
TWS_CHILD|TWS_VISIBLE|TLBS_CHECKBOX, 0 },
{ LISTBOX,"", IDC_LISTBOX3, 8, 41, 5, 16,
TWS_CHILD|TWS_VISIBLE|TLBS_RADIOBOX|TLBS_RIGHT, 0 },
{ BUTTON, "Dlg2", IDC_OPENDLG2, 14, 1, 1, 10, TWS_CHILD|TWS_VISIBLE|TWS_DISABLED, 0 },
{ BUTTON, "Dlg3", IDC_OPENDLG3, 14, 21, 1, 10, TWS_CHILD|TWS_VISIBLE, 0 },
{ BUTTON, "Close", IDC_CLOSE, 14, 41, 1, 11, TWS_CHILD|TWS_VISIBLE, 0 },
{ STATIC, "Esc to exit: ", IDC_STATUSBAR, 24, 0, 1, 80, TWS_CHILD|TWS_VISIBLE|TWS_DISABLED|TSS_LEFT, 0 },
/* the last is the end-of-controls */
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
WNDTEMPL dlg3[] =
{
/* 1st object is always dialog */
{ "mylistctlproc", "Dialog3", 2, 0, 0, 25, 80, TWS_WINDOW, 0 },
/* 2nd and others are controls */
{ LISTCTRL, "", IDC_OK, 1, 1, 16, 79, TWS_CHILD|TWS_VISIBLE, 0 },
{ BUTTON, "Message", IDC_MSG, 20, 20, 1, 15, TWS_CHILD|TWS_VISIBLE, 0 },
{ BUTTON, "Close", IDC_CLOSE, 20, 40, 1, 11, TWS_CHILD|TWS_VISIBLE, 0 },
/* the last is the end-of-controls */
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
WNDTEMPL msgbox[] =
{
/* 1st object is always dialog */
{ "msgbox", "msgbox", 3, 10, 10, 7, 40, TWS_WINDOW, 0 },
/* 2nd and others are controls */
{ STATIC, "This is a message box", IDC_MSG, 1, 1, 1, 38,
TWS_CHILD|TWS_VISIBLE|TSS_CENTER, 0 },
{ BUTTON, "OK", IDC_OK, 3, 5, 1, 10, TWS_CHILD|TWS_VISIBLE, 0 },
{ BUTTON, "Cancel", IDC_CANCEL, 3, 20, 1, 10, TWS_CHILD|TWS_VISIBLE, 0 },
/* the last is the end-of-controls */
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
VOID mywndproc_onselchanged(TWND wnd, TWND ctl)
{
TWND statusbar = 0;
TWND listbox = 0;
INT i = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
statusbar = TuiGetWndItem(wnd, IDC_STATUSBAR);
listbox = ctl;
i = TLB_GetCurSel(listbox);
if (i >= 0)
{
TLB_GetItemText(listbox, i, buf);
TuiSetWndText(statusbar, buf);
}
}
LONG mywndproc(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
CHAR buf[TUI_MAX_WNDTEXT+1];
INT i;
TWND statusbar = 0;
TWND listbox = 0;
TWND edit = 0;
NMHDR* nmhdr = 0;
switch (msg)
{
case TWM_INITDIALOG:
{
listbox = TuiGetWndItem(wnd, IDC_LISTBOX1);
for (i = 0; i < 20; ++i)
{
sprintf(buf, "Item %d", (i));
TLB_AddItem(listbox, buf);
}
TLB_DeleteItem(listbox, 5);
TLB_SetCurSel(listbox, 7);
listbox = TuiGetWndItem(wnd, IDC_LISTBOX2);
for (i = 0; i < 10; ++i)
{
sprintf(buf, "Item %d", (i));
TLB_AddItem(listbox, buf);
}
listbox = TuiGetWndItem(wnd, IDC_LISTBOX3);
for (i = 0; i < 10; ++i)
{
sprintf(buf, "Item %d", (i));
TLB_AddItem(listbox, buf);
}
edit = TuiGetWndItem(wnd, IDC_NAME);
TuiSendMsg(edit, TEM_LIMITTEXT, (WPARAM)20, (LPARAM)0);
statusbar = TuiGetWndItem(wnd, IDC_STATUSBAR);
#ifdef __USE_CURSES__
TuiSendMsg(statusbar, TWM_SETTEXTATTRS, (WPARAM)(A_REVERSE), (LPARAM)0);
#endif
edit = TuiGetWndItem(wnd, IDC_PRICE);
TuiSendMsg(edit, TEM_SETDECWIDTH, (WPARAM)2, (LPARAM)0);
/*
edit = TuiGetWndItem(wnd, IDC_PASSWORD);
TEDT_ShowPasswdChar(edit, TW_HIDE);*/
return TUI_CONTINUE;
}
case TWM_NOTIFY:
{
nmhdr = (NMHDR*)lparam;
switch (nmhdr->code)
{
case TLBN_SELCHANGED:
{
mywndproc_onselchanged(wnd, nmhdr->ctl);
break;
}
}
break;
}
case TWM_COMMAND:
{
sprintf(buf, "Pressed: %s", (IDC_OK == wparam ? "OK" : "Cancel"));
statusbar = TuiGetWndItem(wnd, IDC_STATUSBAR);
TuiSetWndText(statusbar, buf);
if (wparam == IDC_OPENDLG2)
{
}
else if (wparam == IDC_OPENDLG3)
{
TWND dlg = TuiCreateWndTempl(dlg3, 0);
TuiShowWnd(dlg, 1);
}
else if (wparam == IDC_CLOSE)
{
TuiPostQuitMsg(0);
}
break;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
LONG mylistctlproc(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
TWND list = 0;
switch (msg)
{
case TWM_INITDIALOG:
{
list = TuiGetWndItem(wnd, IDC_OK);
#ifdef __USE_CURSES__
TLC_AddColumn(list, "STOCK", 20, ALIGN_LEFT, COLOR_PAIR(BLUE_YELLOW));
TLC_AddColumn(list, "DATE", 16, ALIGN_CENTER, COLOR_PAIR(BLUE_YELLOW));
TLC_AddColumn(list, "OPEN", 16, ALIGN_RIGHT, COLOR_PAIR(BLUE_YELLOW));
TLC_AddColumn(list, "HIGH", 16, ALIGN_RIGHT, COLOR_PAIR(BLUE_YELLOW));
TLC_AddColumn(list, "LOW", 16, ALIGN_RIGHT, COLOR_PAIR(BLUE_YELLOW));
TLC_AddColumn(list, "CLOSE", 16, ALIGN_RIGHT, COLOR_PAIR(BLUE_YELLOW));
#else
TLC_AddColumn(list, "STOCK", 20, ALIGN_LEFT, BLUE_YELLOW);
TLC_AddColumn(list, "DATE", 16, ALIGN_CENTER, BLUE_YELLOW);
TLC_AddColumn(list, "OPEN", 16, ALIGN_RIGHT, BLUE_YELLOW);
TLC_AddColumn(list, "HIGH", 16, ALIGN_RIGHT, BLUE_YELLOW);
TLC_AddColumn(list, "LOW", 16, ALIGN_RIGHT, BLUE_YELLOW);
TLC_AddColumn(list, "CLOSE", 16, ALIGN_RIGHT, BLUE_YELLOW);
#endif
TLC_AddItem(list, "PTT\t01-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t02-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t03-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t04-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t05-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t06-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t07-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t08-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t09-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t10-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t11-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t12-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t13-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t14-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t15-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t16-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t17-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t18-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t19-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t20-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t21-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t22-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t23-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t24-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t25-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t26-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t27-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t28-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t29-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t30-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
return TUI_CONTINUE;
}
case TWM_COMMAND:
{
if (wparam == IDC_CLOSE)
{
TuiDestroyWnd(wnd);
}
else if (wparam == IDC_MSG)
{
UINT rc = TuiMsgBox(wnd,
"Hello world",
"Welcome to the real world.",
MB_YESNOCANCEL);
switch (rc)
{
case MB_YES: TuiMsgBox(wnd, "Hello TUI", "Clicked YES", MB_OK); break;
case MB_NO: TuiMsgBox(wnd, "Hello TUI", "Clicked NO", MB_OK); break;
case MB_CANCEL: TuiMsgBox(wnd, "Hello TUI", "Clicked CANCEL", MB_OK); break;
}
}
break;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
LONG msgboxproc(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_INITDIALOG:
{
#ifdef __USE_CURSES__
TuiSendMsg(wnd, TWM_SETTEXTATTRS, (WPARAM)(A_REVERSE), (LPARAM)0);
#endif
return TUI_CONTINUE;
}
case TWM_COMMAND:
{
if (wparam == IDC_CANCEL)
{
TuiDestroyWnd(wnd);
}
break;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
int main(int argc, char* argv[])
{
MSG msg;
TWND wnd;
TuiStartup();
TuiSetNextMove(TVK_TAB);
TuiRegisterCls("mywndproc", mywndproc);
TuiRegisterCls("mylistctlproc", mylistctlproc);
TuiRegisterCls("msgbox", msgboxproc);
wnd = TuiCreateWndTempl(dlg1, 0);
if (!wnd)
{
TuiShutdown();
return -1;
}
TuiShowWnd(wnd, 1);
while (TuiGetMsg(&msg))
{
TuiDispatchMsg(&msg);
TuiTranslateMsg(&msg);
}
TuiShutdown();
return 0;
}
# File Name: makefile
# Author: Seree Rakwong
# Date: 28-NOV-2017
#
TARGET = tui_test_linux
CC = gcc
CFLAGS = -g -Wall
LFLAGS = -lm -lcurses
.PHONY: default all clean
default: $(TARGET)
all: default
BIN_DIR = ./bin
SRC_DIR = ./src
INC_DIR = ./include
SOURCES = $(SRC_DIR)/tui.c \
$(SRC_DIR)/tdc.c \
$(SRC_DIR)/tmsgbx.c \
$(SRC_DIR)/tstc.c \
$(SRC_DIR)/tedt.c \
$(SRC_DIR)/tbtn.c \
$(SRC_DIR)/tlb.c \
$(SRC_DIR)/tlctl.c \
$(SRC_DIR)/tui_test.c
OBJECTS = $(SOURCES:.c=.o)
INCLUDES = -I$(INC_DIR)
DEFINES = -D__UNIX__ -D__LINUX__ -D__USE_CURSES__
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) -c $< -o $@
$(TARGET): $(OBJECTS)
$(CC) $(CFLAGS) $(LFLAGS) -o $@ $^
clean:
rm -f src/*.o $(TARGET)*
/*-------------------------------------------------------------------
* File name: tui.h
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#ifndef __TEXTUSERINTERFACE_H__
#define __TEXTUSERINTERFACE_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-------------------------------------------------------------------
* defines
*-----------------------------------------------------------------*/
#define TUI_CONTINUE 1
#define TUI_OK 0
#define TUI_ERROR -1
#define TUI_MEM -2
/* miscellaneous */
#define TUI_MAX_WNDTEXT 80
#define TVK_BACK 0x08
#define TVK_TAB 0x09
#define TVK_ENTER 0x0A
#define TVK_SPACE 0x20
#define TVK_PRIOR 0x21
#define TVK_NEXT 0x22
#define TVK_END 0x23
#define TVK_HOME 0x24
#define TVK_LEFT 0x25
#define TVK_UP 0x26
#define TVK_RIGHT 0x27
#define TVK_DOWN 0x28
#define TVK_INSERT 0x2D
#define TVK_DELETE 0x2E
#define TVK_HELP 0x2F
#define TVK_ESCAPE 0x1B
#define TVK_NUMPAD0 0x60
#define TVK_NUMPAD1 0x61
#define TVK_NUMPAD2 0x62
#define TVK_NUMPAD3 0x63
#define TVK_NUMPAD4 0x64
#define TVK_NUMPAD5 0x65
#define TVK_NUMPAD6 0x66
#define TVK_NUMPAD7 0x67
#define TVK_NUMPAD8 0x68
#define TVK_NUMPAD9 0x69
#define TVK_MULTIPLY 0x6A
#define TVK_ADD 0x6B
#define TVK_SEPARATOR 0x6C
#define TVK_SUBTRACT 0x6D
#define TVK_DECIMAL 0x6E
#define TVK_DIVIDE 0x6F
#define TVK_F1 0x70
#define TVK_F2 0x71
#define TVK_F3 0x72
#define TVK_F4 0x73
#define TVK_F5 0x74
#define TVK_F6 0x75
#define TVK_F7 0x76
#define TVK_F8 0x77
#define TVK_F9 0x78
#define TVK_F10 0x79
#define TVK_F11 0x7A
#define TVK_F12 0x7B
#define TVK_F13 0x7C
#define TVK_F14 0x7D
#define TVK_F15 0x7E
#define TVK_F16 0x7F
#define TVK_F17 0x80
#define TVK_F18 0x81
#define TVK_F19 0x82
#define TVK_F20 0x83
#define TVK_F21 0x84
#define TVK_F22 0x85
#define TVK_F23 0x86
#define TVK_F24 0x87
/*
* 0x88 - 0x8F : unassigned
*/
#define TVK_NUMLOCK 0x90
#define TVK_SCROLL 0x91
/*-------------------------------------------------------------------
* types
*-----------------------------------------------------------------*/
typedef long WPARAM;
typedef long LPARAM;
typedef long LONG;
typedef int INT;
typedef void VOID;
typedef void* LPVOID;
typedef const char* LPCSTR;
typedef char* LPSTR;
typedef char CHAR;
typedef double DOUBLE;
typedef unsigned long DWORD;
typedef unsigned int UINT;
typedef char INT8;
typedef unsigned char UINT8;
typedef short INT16;
typedef unsigned short UINT16;
typedef int INT32;
typedef unsigned int UINT32;
typedef long long INT64;
typedef unsigned long long UINT64;
struct _TUIDEVICECONTEXSTRUCT;
typedef struct _TUIDEVICECONTEXSTRUCT _TDC;
typedef struct _TUIDEVICECONTEXSTRUCT *TDC;
struct _TUIWINDOWSTRUCT;
typedef struct _TUIWINDOWSTRUCT _TWND;
typedef struct _TUIWINDOWSTRUCT *TWND;
typedef long (*TWNDPROC)(TWND, UINT, WPARAM, LPARAM);
struct _TUIENVSTRUCT;
typedef struct _TUIENVSTRUCT _TENV;
typedef struct _TUIENVSTRUCT *TENV;
struct _WNDTEMPLSTRUCT
{
LPCSTR clsname;
LPCSTR text;
INT id;
INT y;
INT x;
INT lines;
INT cols;
DWORD style;
INT (*validate)(TWND, LPCSTR);
};
typedef struct _WNDTEMPLSTRUCT WNDTEMPL;
struct _MSGSTRUCT
{
TWND wnd;
UINT msg;
WPARAM wparam;
LPARAM lparam;
};
typedef struct _MSGSTRUCT MSG;
struct _NMHDRSTRUCT
{
INT id;
TWND ctl;
UINT code;
};
typedef struct _NMHDRSTRUCT NMHDR;
struct _RECTSTRUCT
{
INT y;
INT x;
INT lines;
INT cols;
};
typedef struct _RECTSTRUCT RECT;
struct _DRAWITEMSTRUCT
{
INT idx;
RECT rcitem;
};
typedef struct _DRAWITEMSTRUCT DRAWITEM;
/* colors */
/*
216 #define COLOR_BLACK 0
217 #define COLOR_RED 1
218 #define COLOR_GREEN 2
219 #define COLOR_YELLOW 3
220 #define COLOR_BLUE 4
221 #define COLOR_MAGENTA 5
222 #define COLOR_CYAN 6
223 #define COLOR_WHITE 7
*/
#define CYAN_BLACK 1
#define BLACK_CYAN 2
#define GREEN_BLACK 3
#define BLACK_GREEN 4
#define YELLOW_BLACK 5
#define BLACK_YELLOW 6
#define BLUE_YELLOW 7
#define YELLOW_BLUE 8
#define ALIGN_LEFT 0
#define ALIGN_CENTER 1
#define ALIGN_RIGHT 2
#define TW_HIDE 0
#define TW_SHOW 1
/* window styles */
#define TWS_WINDOW 0x00000001
#define TWS_CHILD 0x00000002
#define TWS_VISIBLE 0x00000004
#define TWS_ENABLE 0x00000008
#define TWS_DISABLED 0x00000010
#define TWS_LEFT 0x00000000 /* shared controls style */
#define TWS_CENTER 0x00010000
#define TWS_RIGHT 0x00020000
/* window messages */
#define TWM_FIRST 100
#define TWM_CREATE (TWM_FIRST + 1)
#define TWM_DESTROY (TWM_FIRST + 2)
#define TWM_INITDIALOG (TWM_FIRST + 3)
#define TWM_PAINT (TWM_FIRST + 4)
#define TWM_SETFOCUS (TWM_FIRST + 5)
#define TWM_KILLFOCUS (TWM_FIRST + 6)
#define TWM_KEYDOWN (TWM_FIRST + 7)
#define TWM_KEYUP (TWM_FIRST + 8)
#define TWM_CHAR (TWM_FIRST + 9)
#define TWM_NOTIFY (TWM_FIRST + 10)
#define TWM_ERASEBK (TWM_FIRST + 11)
#define TWM_SETTEXT (TWM_FIRST + 12)
#define TWM_GETTEXT (TWM_FIRST + 13)
#define TWM_SETTEXTALIGN (TWM_FIRST + 14)
#define TWM_COMMAND (TWM_FIRST + 15)
#define TWM_SETTEXTATTRS (TWM_FIRST + 16)
#define TWM_DRAWITEM (TWM_FIRST + 17)
/* application user messages */
#define TWM_USER 10000
/* notification control message */
#define TSN_FIRST (TWM_USER + 100)
#define TEN_FIRST (TWM_USER + 150)
#define TLBN_FIRST (TWM_USER + 200)
#define TBN_FIRST (TWM_USER + 250)
#define TLCN_FIRST (TWM_USER + 300)
/*-------------------------------------------------------------------
* static control
*-----------------------------------------------------------------*/
#define STATIC "STATIC"
#define TSS_LEFT TWS_LEFT
#define TSS_CENTER TWS_CENTER
#define TSS_RIGHT TWS_RIGHT
/*-------------------------------------------------------------------
* edit control
*-----------------------------------------------------------------*/
#define EDIT "EDIT"
#define TES_LEFT TWS_LEFT
#define TES_CENTER TWS_CENTER
#define TES_RIGHT TWS_RIGHT
#define TES_NUMBER 0x00040000
#define TES_UPPERCASE 0x00080000
#define TES_LOWERCASE 0x00100000
#define TES_PASSWORD 0x00200000
#define TES_APPENDMODE 0x00400000
#define TES_AUTOHSCROLL 0x00800000
#define TES_DECIMAL 0x01000000
#define TEM_LIMITTEXT (TWM_USER + 1)
#define TEM_SETPASSWDCHAR (TWM_USER + 2)
#define TEM_SHOWPASSWDCHAR (TWM_USER + 3)
#define TEM_SETDECWIDTH (TWM_USER + 4)
/* edit notified message */
#define TEN_CHANGED (TEN_FIRST + 0)
#define TEN_SETFOCUS (TEN_FIRST + 1)
#define TEN_KILLFOCUS (TEN_FIRST + 2)
/* edit macros */
#define TEDT_LimitText(edt, lim) \
TuiSendMsg(edt, TEM_LIMITTEXT, (WPARAM)lim, (LPARAM)0)
#define TEDT_SetPasswdChar(edt, ch) \
TuiSendMsg(edt, TEM_SETPASSWDCHAR, (WPARAM)ch, (LPARAM)0)
#define TEDT_ShowPasswdChar(edt, show) \
TuiSendMsg(edt, TEM_SHOWPASSWDCHAR, (WPARAM)show, (LPARAM)0)
#define TEDT_SetDecimalWidth(edt, wid) \
TuiSendMsg(edt, TEM_SETDECWIDTH, (WPARAM)wid, (LPARAM)0)
/*-------------------------------------------------------------------
* listbox control
*-----------------------------------------------------------------*/
#define LISTBOX "LISTBOX"
#define LB_OK TUI_OK
#define LB_ERROR TUI_ERROR
#define LB_UNCHECKED 0
#define LB_CHECKED 1
#define TLBS_LEFT TWS_LEFT
#define TLBS_CENTER TWS_CENTER
#define TLBS_RIGHT TWS_RIGHT
#define TLBS_OWNERDRAW 0x00100000
#define TLBS_CHECKBOX 0x00200000
#define TLBS_RADIOBOX 0x00400000
#define TLBM_ADDITEM (TWM_USER + 1)
#define TLBM_DELETEITEM (TWM_USER + 2)
#define TLBM_GETCURSEL (TWM_USER + 3)
#define TLBM_SETCURSEL (TWM_USER + 4)
#define TLBM_DELETEALLITEMS (TWM_USER + 5)
#define TLBM_GETITEMCOUNT (TWM_USER + 6)
#define TLBM_SETITEMDATA (TWM_USER + 7)
#define TLBM_GETITEMDATA (TWM_USER + 8)
#define TLBM_SETITEMTEXT (TWM_USER + 9)
#define TLBM_GETITEMTEXT (TWM_USER + 10)
#define TLBM_SETITEMCHECKED (TWM_USER + 11)
#define TLBM_GETITEMCHECKED (TWM_USER + 12)
#define TLBM_COUNTITEMCHECKED (TWM_USER + 13)
/* listbox notified message */
#define TLBN_SETFOCUS (TLBN_FIRST + 0)
#define TLBN_KILLFOCUS (TLBN_FIRST + 1)
#define TLBN_SELCHANGED (TLBN_FIRST + 2)
/* listbox macros */
#define TLB_AddItem(lbx, text) \
TuiSendMsg(lbx, TLBM_ADDITEM, (WPARAM)0, (LPARAM)text)
#define TLB_DeleteItem(lbx, idx) \
TuiSendMsg(lbx, TLBM_DELETEITEM, (WPARAM)idx, (LPARAM)0)
#define TLB_GetCurSel(lbx) \
TuiSendMsg(lbx, TLBM_GETCURSEL, (WPARAM)0, (LPARAM)0)
#define TLB_SetCurSel(lbx, idx) \
TuiSendMsg(lbx, TLBM_SETCURSEL, (WPARAM)idx, (LPARAM)0)
#define TLB_DeleteAllItems(lbx) \
TuiSendMsg(lbx, TLBM_DELETEALLITEMS, (WPARAM)0, (LPARAM)0)
#define TLB_GetItemCount(lbx) \
TuiSendMsg(lbx, TLBM_GETITEMCOUNT, (WPARAM)0, (LPARAM)0)
#define TLB_SetItemData(lbx, idx, data) \
TuiSendMsg(lbx, TLBM_SETITEMDATA, (WPARAM)idx, (LPARAM)data)
#define TLB_GetItemData(lbx, idx) \
(LPVOID)TuiSendMsg(lbx, TLBM_GETITEMDATA, (WPARAM)idx, (LPARAM)0)
#define TLB_SetItemText(lbx, idx, text) \
TuiSendMsg(lbx, TLBM_SETITEMTEXT, (WPARAM)idx, (LPARAM)text)
#define TLB_GetItemText(lbx, idx, text) \
TuiSendMsg(lbx, TLBM_GETITEMTEXT, (WPARAM)idx, (LPARAM)text)
#define TLB_SetItemChecked(lbx, idx, check) \
TuiSendMsg(lbx, TLBM_SETITEMCHECKED, (WPARAM)idx, (LPARAM)check)
#define TLB_GetItemChecked(lbx, idx) \
TuiSendMsg(lbx, TLBM_GETITEMCHECKED, (WPARAM)idx, (LPARAM)0)
#define TLB_CountItemChecked(lbx) \
TuiSendMsg(lbx, TLBM_COUNTITEMCHECKED, (WPARAM)0, (LPARAM)0)
/*-------------------------------------------------------------------
* button control
*-----------------------------------------------------------------*/
#define BUTTON "BUTTON"
#define TBS_RELEASED 0x0000
#define TBS_PRESSED 0x0001
#define TBS_FOCUSED 0x0002
#define TBN_SETFOCUS (TBN_FIRST + 0)
#define TBN_KILLFOCUS (TBN_FIRST + 1)
/*-------------------------------------------------------------------
* listctrl control
*-----------------------------------------------------------------*/
#define LISTCTRL "LISTCTRL"
#define TLCM_ADDCOLUMN (TWM_USER + 1)
#define TLCM_DELETECOLUMN (TWM_USER + 2)
#define TLCM_DELETEALLCOLUMNS (TWM_USER + 3)
#define TLCM_ADDITEM (TWM_USER + 4)
#define TLCM_DELETEITEM (TWM_USER + 5)
#define TLCM_DELETEALLITEMS (TWM_USER + 6)
#define TLCM_SETITEM (TWM_USER + 7)
#define TLCM_GETITEM (TWM_USER + 8)
#define TLCM_GETITEMCOUNT (TWM_USER + 9)
/*
#define TLCN_FIRST (TWM_USER + 300)
*/
#define LCFM_TEXT 0x0001
#define LCFM_ATTRS 0x0002
#define LCFM_DATA 0x0004
struct _SUBITEMSTRUCT
{
INT col;
INT idx;
CHAR* text;
DWORD attrs;
VOID* data;
};
typedef struct _SUBITEMSTRUCT SUBITEM;
struct _HEADERITEMSTRUCT
{
CHAR* caption;
INT cols;
INT align;
DWORD attrs;
};
typedef struct _HEADERITEMSTRUCT HEADERITEM;
/* listctrl macros */
#define TLC_AddColumn(lc, text, width, al, at) \
do {\
HEADERITEM hdr; \
hdr.caption = text; \
hdr.cols = width; \
hdr.align = al; \
hdr.attrs = at; \
TuiSendMsg(lc, TLCM_ADDCOLUMN, (WPARAM)0, (LPARAM)&hdr); \
} while (0)
#define TLC_DeleteColumn(lc, col) \
TuiSendMsg(lc, TLCM_DELETECOLUMN, (WPARAM)col, (LPARAM)0)
#define TLC_DeleteAllColumns(lc) \
TuiSendMsg(lc, TLCM_DELETEALLCOLUMNS, (WPARAM)0, (LPARAM)0)
#define TLC_AddItem(lc, text, nitems) \
TuiSendMsg(lc, TLCM_ADDITEM, (WPARAM)nitems, (LPARAM)text)
#define TLC_DeleteItem(lc, idx) \
TuiSendMsg(lc, TLCM_DELETEITEM, (WPARAM)idx, (LPARAM)0)
#define TLC_DeleteAllItems(lc) \
TuiSendMsg(lc, TLCM_DELETEALLITEMS, (WPARAM)0, (LPARAM)0)
#define TLC_SetItem(lc, flags, item) \
TuiSendMsg(lc, TLCM_SETITEMTEXT, (WPARAM)flags, (LPARAM)&subitem)
#define TLC_GetItem(lc, flags, item) \
TuiSendMsg(lc, TLCM_GETITEMTEXT, (WPARAM)flags, (LPARAM)&subitem);
#define TLC_GetItemCount(lc) \
TuiSendMsg(lc, TLCM_GETITEMCOUNT, (WPARAM)0, (LPARAM)0)
/*-------------------------------------------------------------------
* window functions
*-----------------------------------------------------------------*/
/*
* TuiStartup()
* Start TUI environment
*/
LONG TuiStartup();
/*
* TuiShutdown()
* End TUI environment
*/
void TuiShutdown();
/*
* TuiGetEnv()
* Get TUI environment
*/
TENV TuiGetEnv();
VOID TuiSetNextMove(LONG nextmove);
UINT TuiGetDlgMsgID();
/* window message functions */
LONG TuiDefWndProc(TWND, UINT, WPARAM, LPARAM);
LONG TuiRegisterCls(LPCSTR clsname, TWNDPROC wndproc);
LONG TuiGetMsg(MSG* msg);
LONG TuiDispatchMsg(MSG* msg);
LONG TuiTranslateMsg(MSG* msg);
LONG TuiPostQuitMsg(LONG exitcode);
LONG TuiSendMsg(TWND, UINT, WPARAM, LPARAM);
LONG TuiPostMsg(TWND, UINT, WPARAM, LPARAM);
/* window functions */
TWND TuiCreateWnd(
LPCSTR clsname,
LPCSTR wndname,
DWORD style,
INT y,
INT x,
INT lines,
INT cols,
TWND parent,
INT id,
LPVOID param
);
TWND TuiCreateWndTempl(
WNDTEMPL* templs,
LPVOID param
);
void TuiDestroyWnd(TWND);
TWND TuiGetActiveChildWnd(TWND);
TWND TuiGetFirstActiveChildWnd(TWND);
TWND TuiGetLastActiveChildWnd(TWND);
TWND TuiGetNextActiveChildWnd(TWND);
TWND TuiGetPrevActiveChildWnd(TWND);
TWND TuiGetActiveWnd();
TWND TuiGetFirstWnd();
TWND TuiGetLastWnd();
TWND TuiGetNextWnd(TWND wnd);
TWND TuiGetPrevWnd(TWND wnd);
LONG TuiInvalidateWnd(TWND);
LONG TuiShowWnd(TWND, LONG);
LONG TuiEnableWnd(TWND, LONG);
LONG TuiIsWndEnabled(TWND);
LONG TuiIsWndVisible(TWND);
TWND TuiGetWndItem(TWND, INT);
LONG TuiGetWndText(TWND, LPSTR, LONG);
VOID TuiSetWndText(TWND, LPCSTR);
TWND TuiGetParent(TWND);
LONG TuiSetFocus(TWND);
LONG TuiMoveWnd(TWND, INT, INT, INT, INT);
LONG TuiGetWndRect(TWND, RECT*);
DWORD TuiGetWndStyle(TWND);
DWORD TuiSetWndStyle(TWND, DWORD);
DWORD TuiGetWndTextAttrs(TWND);
DWORD TuiSetWndTextAttrs(TWND, DWORD);
UINT TuiGetWndID(TWND);
LPVOID TuiGetWndParam(TWND);
LPVOID TuiSetWndParam(TWND, LPVOID);
LONG TuiIsWndValidate(TWND, LPCSTR);
VOID TuiSetWndValidate(TWND, LONG (*)(TWND, LPCSTR));
#define MB_INVALID 0x00000000
#define MB_CAPTION 0x00010000
#define MB_YES 0x00000001
#define MB_NO 0x00000002
#define MB_CANCEL 0x00000004
#define MB_YESNOCANCEL (MB_YES|MB_NO|MB_CANCEL)
#define MB_YESNO (MB_YES|MB_NO)
#define MB_OK 0x00000008
#define MB_OKCANCEL (MB_OK|MB_CANCEL)
UINT TuiEndDlg(TWND, UINT);
UINT TuiMsgBox(TWND, LPCSTR, LPCSTR, UINT);
/* device context */
#define DT_LEFT 0x0001
#define DT_CENTER 0x0002
#define DT_RIGHT 0x0003
struct _TUIDEVICECONTEXSTRUCT
{
#ifdef __USE_CURSES__
WINDOW* win;
#elif defined __USE_QIO__
/* QIO for VMS implement here */
struct qio_fields* win;
#endif
};
TDC TuiGetDC(TWND);
LONG TuiDrawText(TDC, INT, INT, LPCSTR, DWORD);
LONG TuiDrawTextEx(TDC, INT, INT, INT, LPCSTR, LONG, DWORD, INT);
LONG TuiPutChar(TDC, INT, INT, CHAR, DWORD);
LONG TuiMoveYX(TDC, INT, INT);
LONG TuiGetYX(TDC, INT*, INT*);
LONG TuiPrintTextAlignment(LPSTR out, LPSTR in, LONG limit, INT align);
/* simple macros */
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#ifdef __cplusplus
}
#endif
#endif /*__TEXTUSERINTERFACE_H__*/
/*-------------------------------------------------------------------
* File name: tui.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
struct _TWNDPROCSTRUCT
{
TWNDPROC wndproc;
LPCSTR clsname;
struct _TWNDPROCSTRUCT *prev;
struct _TWNDPROCSTRUCT *next;
};
typedef struct _TWNDPROCSTRUCT twndproc_t;
struct _TUIMSGQUEUESTRUCT
{
TWND wnd;
UINT msg;
WPARAM wparam;
LPARAM lparam;
struct _TUIMSGQUEUESTRUCT *next;
};
typedef struct _TUIMSGQUEUESTRUCT tmsgq_t;
struct _TUIENVSTRUCT
{
/* doubly linked-list */
twndproc_t* firstproc;
twndproc_t* lastproc;
/* que */
tmsgq_t* headq;
tmsgq_t* tailq;
/* doubly linked-list */
TWND firstwnd;
TWND lastwnd;
TWND activewnd;
LONG quitcode;
LONG exitcode;
LONG nextmove; /* to identify the next control moved */
LONG prevmove; /* to identify the prev control moved */
LONG notifykey;
_TDC dc;
/* last dialog returned message */
UINT dlgmsgid;
};
struct _TUIWINDOWSTRUCT
{
LPCSTR clsname;
CHAR wndname[TUI_MAX_WNDTEXT+1];
DWORD style;
DWORD exstyle;
INT x;
INT y;
INT cols;
INT lines;
TWND parent;
UINT id;
LPVOID param;
TWNDPROC wndproc;
LONG enable;
LONG visible;
LONG (*validate)(TWND, LPCSTR);
/* curses lib */
#ifdef __USE_CURSES__
WINDOW* win;
#elif defined __USE_QIO__
/* QIO for VMS implement here */
struct qio_fields* win;
#endif
DWORD attrs;
/* last dialog returned message */
UINT dlgmsgid;
/* links */
TWND prevwnd;
TWND nextwnd;
TWND firstchild;
TWND lastchild;
TWND activechild;
};
/*-------------------------------------------------------------------
* global storages
*-----------------------------------------------------------------*/
TENV genvptr = 0;
/*-------------------------------------------------------------------
* internal functions
*-----------------------------------------------------------------*/
twndproc_t* _TuiFindWndProc(LPCSTR clsname);
TWND _TuiCreateWnd(
LPCSTR clsname,
LPCSTR wndname,
DWORD style,
INT y,
INT x,
INT lines,
INT cols,
TWND parent,
UINT id,
LPVOID param
);
VOID _TuiDestroyWnd(TWND wnd);
LONG _TuiInvalidateWnd(TWND wnd);
LONG _TuiDequeMsg();
LONG _TuiRemoveAllMsgs();
LONG _TuiAlignmentPrint(LPSTR out, LPSTR in, LONG limit, INT align);
LONG STATICPROC(TWND, UINT, WPARAM, LPARAM);
LONG EDITPROC(TWND, UINT, WPARAM, LPARAM);
LONG LISTBOXPROC(TWND, UINT, WPARAM, LPARAM);
LONG BUTTONPROC(TWND, UINT, WPARAM, LPARAM);
LONG LISTCTRLPROC(TWND, UINT, WPARAM, LPARAM);
#define MSGBOX "MSGBOX"
LONG MSGBOXPROC(TWND, UINT, WPARAM, LPARAM);
/*-------------------------------------------------------------------
* functions
*-----------------------------------------------------------------*/
#ifdef __USE_QIO__
int printf(const char *format, ...);
int sprintf(char *str, const char *format, ...);
LONG QIO_Initialize();
VOID QIO_Get();
VOID QIO_Put();
VOID DoUpdate() /* required by QIO */
{
return;
}
VOID CheckTerm() /* required by QIO */
{
return;
}
#endif /*__USE_QIO__*/
LONG TuiStartup()
{
TENV env = (TENV)malloc(sizeof(_TENV));
if (env)
{
genvptr = env;
memset(env, 0, sizeof(_TENV));
/* register standard controls */
TuiRegisterCls(STATIC, STATICPROC);
TuiRegisterCls(EDIT, EDITPROC);
TuiRegisterCls(LISTBOX, LISTBOXPROC);
TuiRegisterCls(BUTTON, BUTTONPROC);
TuiRegisterCls(LISTCTRL, LISTCTRLPROC);
TuiRegisterCls(MSGBOX, MSGBOXPROC);
/* device context */
#ifdef __USE_CURSES__
/* curses lib */
initscr();
cbreak();
keypad(stdscr, TRUE);
noecho();
start_color();
init_pair(CYAN_BLACK, COLOR_CYAN, COLOR_BLACK);
init_pair(BLACK_CYAN, COLOR_BLACK, COLOR_GREEN);
init_pair(GREEN_BLACK, COLOR_GREEN, COLOR_BLACK);
init_pair(BLACK_GREEN, COLOR_BLACK, COLOR_GREEN);
init_pair(YELLOW_BLACK, COLOR_YELLOW, COLOR_BLACK);
init_pair(BLACK_YELLOW, COLOR_BLACK, COLOR_YELLOW);
init_pair(BLUE_YELLOW, COLOR_BLUE, COLOR_YELLOW);
init_pair(YELLOW_BLUE, COLOR_YELLOW, COLOR_BLUE);
env->dc.win = stdscr;
env->nextmove = TVK_ENTER;
env->prevmove = KEY_BTAB;
env->notifykey = TVK_ENTER;
#elif defined __USE_QIO__
/* QIO for VMS implement here */
if (!QIO_Initialize())
{
free(env);
genvptr = 0;
}
env->dc.win = &qio_field;
#endif
}
return (genvptr ? TUI_OK : TUI_ERROR);
}
VOID TuiShutdown()
{
TWND wnd = genvptr->firstwnd;
TWND temp = 0;
while (wnd)
{
temp = wnd;
wnd = wnd->nextwnd;
TuiDestroyWnd(temp);
}
free(genvptr);
genvptr = 0;
#ifdef __USE_CURSES__
echo();
nocbreak();
endwin();
#elif defined __USE_QIO__
/* QIO for VMS implement here */
#endif
}
twndproc_t* _TuiFindWndProc(LPCSTR clsname)
{
TENV env = genvptr;
twndproc_t* proc = env->firstproc;
while (proc)
{
if (strcmp(proc->clsname, clsname) == 0)
{
break;
}
proc = proc->next;
}
return proc;
}
TENV TuiGetEnv()
{
return genvptr;
}
VOID TuiSetNextMove(LONG nextmove)
{
TENV env = genvptr;
env->nextmove = nextmove;
}
UINT TuiGetDlgMsgID()
{
TENV env = genvptr;
return env->dlgmsgid;
}
TDC TuiGetDC(TWND wnd)
{
static _TDC dc;
#ifdef __USE_CURSES__
if (wnd)
{
dc.win = wnd->win;
}
else
{
dc.win = stdscr;
}
#elif defined __USE_QIO__
/* QIO for VMS implement here */
if (wnd)
{
dc.win = wnd->win;
}
else
{
dc = genvptr->dc;
}
#endif
return (TDC)&dc;
}
LONG TuiRegisterCls(LPCSTR clsname, TWNDPROC wndproc)
{
TENV env = genvptr;
twndproc_t* proc = _TuiFindWndProc(clsname);
if (!proc)
{
proc = (twndproc_t*)malloc(sizeof(twndproc_t));
proc->clsname = clsname;
proc->wndproc = wndproc;
proc->prev = 0;
proc->next = 0;
if (env->firstproc)
{
proc->prev = env->lastproc;
env->lastproc->next = proc;
env->lastproc = proc;
}
else
{
env->firstproc = env->lastproc = proc;
}
}
return TUI_OK;
}
LONG TuiMoveWnd(TWND wnd, INT y, INT x, INT lines, INT cols)
{
LONG rc = TUI_OK;
wnd->y = y;
wnd->x = x;
wnd->lines = lines;
wnd->cols = cols;
return rc;
}
TWND _TuiCreateWnd(
LPCSTR clsname,
LPCSTR wndname,
DWORD style,
INT y,
INT x,
INT lines,
INT cols,
TWND parent,
UINT id,
LPVOID param
)
{
TENV env = genvptr;
TWND wnd = 0;
LONG len = 0;
twndproc_t* proc = _TuiFindWndProc(clsname);
if ((style & TWS_WINDOW) &&
(style & TWS_CHILD))
{
/* not allow creating both styles at a time */
return wnd;
}
else if (style & TWS_CHILD && !parent)
{
/* not allow child without parent */
return wnd;
}
if (proc)
{
wnd = (TWND)malloc(sizeof(_TWND));
if (wnd)
{
memset(wnd, 0, sizeof(_TWND));
wnd->clsname = clsname;
len = strlen(wndname);
if (wndname && len > 0)
{
if (len > TUI_MAX_WNDTEXT)
{
strncpy(wnd->wndname, wndname, TUI_MAX_WNDTEXT);
}
else
{
strcpy(wnd->wndname, wndname);
}
}
wnd->style = style;
wnd->parent = parent;
wnd->id = id;
wnd->wndproc = proc->wndproc;
wnd->enable = (style & TWS_DISABLED ? 0 : 1);
wnd->visible = (style & TWS_VISIBLE ? 1 : 0);
wnd->validate = 0;
/* curses */
#ifdef __USE_CURSES__
wnd->win = stdscr;
#elif defined __USE_QIO__
/* QIO for VMS implement here */
wnd->win = &qio_field;
#endif
wnd->attrs = 0;
/* make link */
if (style & TWS_WINDOW)
{
if (env->firstwnd)
{
wnd->prevwnd = env->lastwnd;
env->lastwnd->nextwnd = wnd;
env->lastwnd = wnd;
}
else
{
env->firstwnd = env->lastwnd = wnd;
}
env->activewnd = wnd;
env->dlgmsgid = MB_INVALID;
#ifdef __USE_CURSES__
wnd->y = (y > 0 && y < LINES ? y : 0);
wnd->x = (x > 0 && x < COLS ? x : 0);
wnd->lines = (lines > 0 && lines < LINES ? lines : LINES);
wnd->cols = (cols > 0 && cols < COLS ? cols : COLS);
#elif defined __USE_QIO__
/* QIO for VMS implement here */
wnd->y = y;
wnd->x = x;
wnd->lines = lines;
wnd->cols = cols;
#endif
}
else if (style & TWS_CHILD)
{
if (parent->firstchild)
{
wnd->prevwnd = parent->lastchild;
parent->lastchild->nextwnd = wnd;
parent->lastchild = wnd;
}
else
{
parent->firstchild = parent->lastchild = wnd;
}
/* re-size window rectangle */
wnd->y = (parent->y + y);
wnd->x = (parent->x + x);
wnd->lines = (lines > parent->lines ? parent->lines : lines);
wnd->cols = (cols > parent->cols ? parent->cols : cols);
/* send message */
TuiSendMsg(wnd, TWM_ERASEBK, (WPARAM)TuiGetDC(wnd), 0);
TuiSendMsg(wnd, TWM_CREATE, 0, 0);
}
}
}
return wnd;
}
TWND TuiCreateWnd(
LPCSTR clsname,
LPCSTR wndname,
DWORD style,
INT y,
INT x,
INT lines,
INT cols,
TWND parent,
INT id,
LPVOID param
)
{
LONG rc = TUI_CONTINUE;
TWND child = 0;
TWND wnd = _TuiCreateWnd(
clsname,
wndname,
style,
y,
x,
lines,
cols,
parent,
id,
param
);
if (wnd)
{
TuiSendMsg(wnd, TWM_ERASEBK, (WPARAM)TuiGetDC(wnd), 0);
rc = TuiSendMsg(wnd, TWM_CREATE, 0, (LPARAM)param);
if (rc != TUI_CONTINUE)
{
if (wnd)
{
_TuiDestroyWnd(wnd);
}
wnd = 0;
}
child = TuiGetFirstActiveChildWnd(wnd);
if (child)
{
wnd->activechild = child;
TuiSetFocus(child);
}
}
return wnd;
}
TWND TuiCreateWndTempl(
WNDTEMPL* templs,
LPVOID param
)
{
LONG rc = TUI_CONTINUE;
TWND wnd = 0;
TWND child = 0;
int i = 0;
if (templs)
{
wnd = _TuiCreateWnd(
templs[i].clsname,
templs[i].text,
templs[i].style,
templs[i].y,
templs[i].x,
templs[i].lines,
templs[i].cols,
0,
0,
param
);
if (wnd)
{
for (i = 1; templs[i].clsname; ++i)
{
child = _TuiCreateWnd(
templs[i].clsname,
templs[i].text,
templs[i].style,
templs[i].y,
templs[i].x,
templs[i].lines,
templs[i].cols,
wnd,
templs[i].id,
0
);
if (!child)
{
_TuiDestroyWnd(wnd);
wnd = 0;
}
else
{
child->validate = (LONG (*)(TWND, LPCSTR))templs[i].validate;
}
} /* create children */
} /* wnd is created successfully */
if (wnd)
{
TuiSendMsg(wnd, TWM_ERASEBK, (WPARAM)TuiGetDC(wnd), 0);
rc = TuiSendMsg(wnd, TWM_INITDIALOG, (WPARAM)0, (LPARAM)0);
if (rc != TUI_CONTINUE)
{
_TuiDestroyWnd(wnd);
wnd = 0;
}
child = TuiGetFirstActiveChildWnd(wnd);
if (child)
{
wnd->activechild = child;
TuiSetFocus(child);
}
}
} /* templs is allocated */
return wnd;
}
void _TuiDestroyWnd(TWND wnd)
{
TWND child = (wnd ? wnd->firstchild : 0);
TWND temp = child;
while (child)
{
child = child->nextwnd;
free(temp);
temp->nextwnd = temp->prevwnd = 0;
temp = child;
}
wnd->nextwnd = wnd->prevwnd = 0;
free(wnd);
}
void TuiDestroyWnd(TWND wnd)
{
TENV env = genvptr;
/* remove the link if it is TWS_WINDOW */
if (wnd->style & TWS_WINDOW)
{
env->lastwnd = wnd->prevwnd;
if (env->lastwnd)
{
env->lastwnd->nextwnd = 0;
}
env->activewnd = env->lastwnd;
}
/* save the last message id */
env->dlgmsgid = wnd->dlgmsgid;
TuiSendMsg(wnd, TWM_DESTROY, 0, 0);
_TuiDestroyWnd(wnd);
if (env->activewnd)
{
TuiInvalidateWnd(env->activewnd);
}
}
LONG TuiPostMsg(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (wnd)
{
tmsgq_t* msgq = (tmsgq_t*)malloc(sizeof(tmsgq_t));
if (msgq)
{
TENV env = genvptr;
memset(msgq, 0, sizeof(tmsgq_t));
msgq->wnd = wnd;
msgq->msg = msg;
msgq->wparam = wparam;
msgq->lparam = lparam;
if (env->tailq)
{
env->tailq->next = msgq;
}
else
{
env->headq = env->tailq = msgq;
}
return TUI_OK;
}
}
return TUI_ERROR;
}
LONG TuiSendMsg(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (wnd)
{
/*
TENV env = genvptr;
tmsgq_t* msgq = 0;
while (env->headq)
{
msgq = env->headq;
msgq->wnd->wndproc(msgq->wnd,
msgq->msg,
msgq->wparam,
msgq->lparam);
env->headq = env->headq->next;
free(msgq);
}
env->headq = env->tailq = 0;
*/
return wnd->wndproc(wnd, msg, wparam, lparam);
}
return TUI_ERROR;
}
LONG _TuiInvalidateWnd(TWND wnd)
{
TWND activechild = TuiGetActiveChildWnd(wnd);
TWND child = wnd->firstchild;
TuiSendMsg(wnd, TWM_ERASEBK, (WPARAM)TuiGetDC(wnd), 0);
TuiSendMsg(wnd, TWM_PAINT, 0, 0);
while (child)
{
TuiSendMsg(child, TWM_ERASEBK, (WPARAM)TuiGetDC(wnd), 0);
TuiSendMsg(child, TWM_PAINT, 0, 0);
child = child->nextwnd;
}
if (!activechild)
{
activechild = TuiGetFirstActiveChildWnd(wnd);
}
if (activechild)
{
TuiMoveYX(TuiGetDC(activechild), activechild->y, activechild->x);
}
return TUI_OK;
}
LONG TuiInvalidateWnd(TWND wnd)
{
return _TuiInvalidateWnd(wnd);
}
LONG TuiShowWnd(TWND wnd, LONG show)
{
wnd->visible = show;
return _TuiInvalidateWnd(wnd);
}
LONG TuiEnableWnd(TWND wnd, LONG enable)
{
wnd->enable = enable;
return _TuiInvalidateWnd(wnd);
}
TWND TuiGetFirstActiveChildWnd(TWND wnd)
{
if (wnd)
{
TWND activechild = wnd->activechild;
TWND firstwnd = 0;
wnd->activechild = wnd->lastchild;
firstwnd = TuiGetNextActiveChildWnd(wnd);
wnd->activechild = activechild;
return firstwnd;
}
return 0;
}
TWND TuiGetLastActiveChildWnd(TWND wnd)
{
if (wnd)
{
TWND activechild = wnd->activechild;
TWND lastwnd = 0;
wnd->activechild = wnd->firstchild;
lastwnd = TuiGetPrevActiveChildWnd(wnd);
wnd->activechild = activechild;
return lastwnd;
}
return 0;
}
TWND TuiGetPrevActiveChildWnd(TWND wnd)
{
TWND activechild = (wnd ? wnd->activechild : 0);
if (!activechild && wnd)
{
activechild = wnd->lastchild;
}
else if (activechild)
{
activechild = activechild->prevwnd;
if (!activechild && wnd)
{
activechild = wnd->lastchild;
}
}
while (activechild)
{
if (TuiIsWndVisible(activechild))
{
if (TuiIsWndEnabled(activechild))
{
if (strcmp(activechild->clsname, STATIC) != 0)
{
break; /* found the next control */
}
}
}
activechild = activechild->prevwnd;
}
return activechild;
}
TWND TuiGetActiveChildWnd(TWND wnd)
{
TWND parent = (wnd ? wnd->parent : 0);
return (wnd ? wnd->activechild : parent);
}
TWND TuiGetNextActiveChildWnd(TWND wnd)
{
TWND activechild = (wnd ? wnd->activechild : 0);
if (!activechild && wnd)
{
activechild = wnd->firstchild;
}
else if (activechild)
{
activechild = activechild->nextwnd;
if (!activechild && wnd)
{
activechild = wnd->firstchild;
}
}
while (activechild)
{
if (TuiIsWndVisible(activechild))
{
if (TuiIsWndEnabled(activechild))
{
if (strcmp(activechild->clsname, STATIC) != 0)
{
break; /* found the next control */
}
}
}
activechild = activechild->nextwnd;
}
return activechild;
}
LONG TuiIsWndEnabled(TWND wnd)
{
if (!wnd)
{
return TUI_ERROR;
}
return wnd->enable;
}
LONG TuiIsWndVisible(TWND wnd)
{
if (!wnd)
{
return TUI_ERROR;
}
return wnd->visible;
}
TWND TuiGetWndItem(TWND wnd, INT id)
{
TWND child = wnd->firstchild;
while (child)
{
if (child->id == id)
{
break;
}
child = child->nextwnd;
}
return child;
}
LONG TuiGetWndRect(TWND wnd, RECT* rect)
{
rect->y = wnd->y;
rect->x = wnd->x;
rect->lines = wnd->lines;
rect->cols = wnd->cols;
return TUI_OK;
}
DWORD TuiGetWndTextAttrs(TWND wnd)
{
return wnd->attrs;
}
DWORD TuiSetWndTextAttrs(TWND wnd, DWORD newattrs)
{
DWORD oldattrs = wnd->attrs;
wnd->attrs = newattrs;
return oldattrs;
}
DWORD TuiGetWndStyle(TWND wnd)
{
return wnd->style;
}
DWORD TuiSetWndStyle(TWND wnd, DWORD newstyle)
{
DWORD oldstyle = wnd->style;
wnd->style = newstyle;
return oldstyle;
}
UINT TuiGetWndID(TWND wnd)
{
return wnd->id;
}
LPVOID TuiGetWndParam(TWND wnd)
{
return wnd->param;
}
LPVOID TuiSetWndParam(TWND wnd, LPVOID newparam)
{
LPVOID oldparam = wnd->param;
wnd->param = newparam;
return oldparam;
}
LONG TuiIsWndValidate(TWND wnd, LPCSTR text)
{
LONG rc = TUI_CONTINUE;
if (wnd->validate)
{
rc = wnd->validate(wnd, text);
}
return rc;
}
VOID
TuiSetWndValidate(TWND wnd, LONG (*validate)(TWND, LPCSTR))
{
wnd->validate = validate;
}
LONG TuiGetWndText(TWND wnd, LPSTR text, LONG cb)
{
LONG len = (wnd ? strlen(wnd->wndname) : 0);
if (cb < 0)
{
return len;
}
memset(text, 0, cb);
if (cb > len)
{
cb = len;
}
strncpy(text, wnd->wndname, cb);
return strlen(text);
}
VOID TuiSetWndText(TWND wnd, LPCSTR text)
{
LONG len = 0;
if (text && wnd)
{
len = strlen(text);
if (len > TUI_MAX_WNDTEXT)
{
strncpy(wnd->wndname, text, TUI_MAX_WNDTEXT);
}
else
{
strcpy(wnd->wndname, text);
}
TuiInvalidateWnd(wnd);
}
}
TWND TuiGetParent(TWND wnd)
{
if (wnd)
{
return wnd->parent;
}
return 0;
}
/*-------------------------------------------------------------------
* MSG functions
*-----------------------------------------------------------------*/
#ifdef __USE_QIO__
VOID QIO_GetCh()
{
QIO_InitParameter();
while(1)
{
QIO_GetKeyTerminal();
switch(bProcess)
{
case ENDERR:
printf("Program abort...\n");
exit(0);
case BEGPROC:
QIO_InitParameter();
break;
case ENDSUCC:
CheckProcessInput();
if(CheckValue()== TRUE)
{
memset(qio_field.szDefault,0,SIZE_TEXT);
return;
}
}
}
}
#endif
LONG TuiGetMsg(MSG* msg)
{
TENV env = genvptr;
tmsgq_t* msgq = 0;
if (env->quitcode)
{
return 0;
}
/* deque */
while (env->headq)
{
msgq = env->headq;
msgq->wnd->wndproc(msgq->wnd,
msgq->msg,
msgq->wparam,
msgq->lparam);
env->headq = env->headq->next;
free(msgq);
}
env->tailq = env->headq; /* set to nil */
memset(msg, 0, sizeof(MSG));
msg->wnd = env->activewnd;
#ifdef __USE_CURSES__
msg->wparam = wgetch(stdscr);
#elif defined __USE_QIO__
/*printf("%s", sQioClear);*/
/*QIO_Text(5, 1, 'W', sPrompt);*/
qio_field.lType = QIO_ANY /*| QIO_UPPERCASE*/ | QIO_NO_ECHO;
qio_field.cColor = 'W';
/*sprintf(qio_field.szHelp, "%s", "Enter password");*/
/*strcpy(qio_field.szHelp, "");*/
qio_field.lLength = 1;
qio_field.lRow = 1;
qio_field.lColumn = 1;/*strlen(sPrompt)+1;*/
qio_field.bReprint = 0;
QIO_Get();
/*printf("\n");*/
/*
memcpy(sInput, qio_field.szResult, MAX_PUBKEY_LEN+MAX_LEN_PWD);
*/
msg->wparam = qio_field.lTerm;
#endif
return msg->wparam;
}
LONG _TuiAlignmentPrint(LPSTR out, LPSTR in, LONG limit, INT align)
{
LONG len = 0;
CHAR text[TUI_MAX_WNDTEXT+1];
INT firstlen = 0;
INT lastlen = 0;
len = strlen(in);
if (len > limit)
{
len = limit;
}
memset(text, 0, TUI_MAX_WNDTEXT);
if ((ALIGN_CENTER == align) || (TWS_CENTER & align))
{
firstlen = (limit - len)/2;
lastlen = limit - (len + firstlen);
if (firstlen > 0 && lastlen > 0)
{
sprintf(text, "%*s%s%*s",
firstlen, " ",
in,
lastlen, " ");
}
else if (lastlen > 0)
{
sprintf(text, "%s%*s",
in,
lastlen, " ");
}
else
{
sprintf(text, "%s", in);
}
}
else if ((ALIGN_RIGHT == align) || (TWS_RIGHT & align))
{
sprintf(text, "%*s",
(INT)(limit),
in);
}
else
{
sprintf(text, "%-*s",
(INT)(limit),
in);
}
strcpy(out, text);
return strlen(out);
}
LONG _TuiRemoveAllMsgs()
{
TENV env = genvptr;
tmsgq_t* msgq = 0;
/* deque */
while (env->headq)
{
msgq = env->headq;
if (env->headq)
{
env->headq = env->headq->next;
}
msgq->next = 0;
free(msgq);
}
env->tailq = env->headq = 0;
return TUI_OK;
}
LONG _TuiDequeMsg()
{
TENV env = genvptr;
tmsgq_t* msgq = 0;
/* deque */
while (env->headq)
{
msgq = env->headq;
TuiSendMsg(msgq->wnd,
msgq->msg,
msgq->wparam,
msgq->lparam);
if (env->headq)
{
env->headq = env->headq->next;
}
msgq->next = 0;
free(msgq);
}
env->tailq = env->headq = 0;
return TUI_OK;
}
LONG TuiDispatchMsg(MSG* msg)
{
TENV env = genvptr;
TWND wnd = env->activewnd;
TWND child = wnd->activechild;
if (env->quitcode)
{
return TUI_OK;
}
if (child)
{
msg->wnd = child;
}
else if (wnd)
{
child = TuiGetFirstActiveChildWnd(wnd);
if (child)
{
msg->wnd = child;
}
else
{
msg->wnd = wnd;
}
}
/* deque message */
_TuiDequeMsg();
return TUI_OK;
}
LONG TuiTranslateMsg(MSG* msg)
{
TENV env = genvptr;
INT ch = (int)msg->wparam;
LONG rc = 0;
TWND nextwnd = 0;
TWND prevwnd = 0;
TWND parent = 0;
LONG nextmove = env->nextmove;
LONG prevmove = env->prevmove;
if (env->quitcode)
{
return TUI_OK;
}
/* send message to the current active window */
if (!msg->wnd)
{
return TUI_CONTINUE;
}
/* convert keyboard code to message */
switch (ch)
{
#ifdef __USE_CURSES__
/* not support mouse/resize events yet */
case KEY_MOUSE:/* Mouse event has occurred */
#ifdef __LINUX__
case KEY_RESIZE:/* Terminal resize event */
#endif
#elif defined __USE_QIO__
#endif
return 0;
}
/*case TVK_ENTER:*/ /*ENTER*/
if (ch == nextmove)
{
parent = TuiGetParent(msg->wnd);
/* kill focus the current active window */
nextwnd = TuiGetNextActiveChildWnd(parent);
rc = TuiSendMsg(msg->wnd, TWM_KILLFOCUS, 0, (LPARAM)nextwnd);
if (rc != TUI_CONTINUE)
{
return rc;
}
/* set focus the new active window */
prevwnd = msg->wnd;
if (parent)
{
if (msg->wnd == TuiGetLastActiveChildWnd(parent))
{
msg->wnd = TuiGetFirstActiveChildWnd(parent);
}
else
{
msg->wnd = nextwnd;
}
parent->activechild = msg->wnd;
}
else
{
msg->wnd = TuiGetNextActiveChildWnd(env->activewnd);
env->activewnd->activechild = msg->wnd;
}
if (msg->wnd)
{
rc = TuiPostMsg(msg->wnd, TWM_SETFOCUS, 0, (LPARAM)prevwnd);
TuiMoveYX(TuiGetDC(msg->wnd), msg->wnd->y, msg->wnd->x);
}
return 0;
}
else if (ch == prevmove)
{
parent = TuiGetParent(msg->wnd);
/* kill focus the current active window */
prevwnd = TuiGetPrevActiveChildWnd(parent);
rc = TuiSendMsg(msg->wnd, TWM_KILLFOCUS, 0, (LPARAM)prevwnd);
if (rc != TUI_CONTINUE)
{
return rc;
}
/* set focus the new active window */
nextwnd = msg->wnd;
if (parent)
{
if (msg->wnd == TuiGetFirstActiveChildWnd(parent))
{
msg->wnd = TuiGetLastActiveChildWnd(parent);
}
else
{
msg->wnd = prevwnd;
}
parent->activechild = msg->wnd;
}
else
{
msg->wnd = TuiGetPrevActiveChildWnd(env->activewnd);
env->activewnd->activechild = msg->wnd;
}
if (msg->wnd)
{
rc = TuiPostMsg(msg->wnd, TWM_SETFOCUS, 0, (LPARAM)nextwnd);
TuiMoveYX(TuiGetDC(msg->wnd), msg->wnd->y, msg->wnd->x);
}
return 0;
}
/* parent window */
rc = TuiSendMsg(env->activewnd, TWM_KEYDOWN, msg->wparam, 0);
rc = TuiSendMsg(env->activewnd, TWM_CHAR, msg->wparam, 0);
rc = TuiSendMsg(env->activewnd, TWM_KEYUP, msg->wparam, 0);
if (msg->wnd != env->activewnd)
{
rc = TuiSendMsg(msg->wnd, TWM_KEYDOWN, msg->wparam, 0);
rc = TuiSendMsg(msg->wnd, TWM_CHAR, msg->wparam, 0);
rc = TuiSendMsg(msg->wnd, TWM_KEYUP, msg->wparam, 0);
}
/* deque */
/*
while (env->headq)
{
msgq = env->headq;
TuiSendMsg(msgq->wnd,
msgq->msg,
msgq->wparam,
msgq->lparam);
env->headq = env->headq->next;
free(msgq);
}
env->tailq = env->headq;
*/
TuiDispatchMsg(msg);
return 0;
}
LONG TuiPostQuitMsg(LONG exitcode)
{
TENV env = genvptr;
env->quitcode = 1;
env->exitcode = exitcode;
return TUI_OK;
}
LONG TuiSetFocus(TWND wnd)
{
TENV env = genvptr;
TWND parent = (wnd ? wnd->parent : env->activewnd);
TWND activewnd = TuiGetActiveChildWnd(wnd);
LONG rc = TUI_CONTINUE;
/* kill focus at the current control */
rc = TuiSendMsg(activewnd, TWM_KILLFOCUS, 0, (LPARAM)wnd);
if (rc != TUI_CONTINUE)
{
return rc;
}
if (wnd)
{
rc = TuiSendMsg(wnd, TWM_SETFOCUS, 0, (LPARAM)activewnd);
TuiMoveYX(TuiGetDC(wnd), wnd->y, wnd->x);
parent->activechild = wnd;
}
return rc;
}
TWND TuiGetActiveWnd()
{
TENV env = genvptr;
return env->activewnd;
}
TWND TuiGetFirstWnd()
{
TENV env = genvptr;
return env->firstwnd;
}
TWND TuiGetLastWnd()
{
TENV env = genvptr;
return env->lastwnd;
}
TWND TuiGetNextWnd(TWND wnd)
{
return wnd->nextwnd;
}
TWND TuiGetPrevWnd(TWND wnd)
{
return wnd->prevwnd;
}
LONG TuiPrintTextAlignment(LPSTR out, LPSTR in, LONG limit, INT align)
{
return _TuiAlignmentPrint(out, in, limit, align);
}
/*-------------------------------------------------------------------
* DefWndProc functions
*-----------------------------------------------------------------*/
LONG _TuiDefWndProc_OnEraseBk(TWND wnd, TDC dc);
VOID _TuiDefWndProc_OnSetText(TWND wnd, LPCSTR text);
LONG _TuiDefWndProc_OnGetText(TWND wnd, LPSTR text, LONG cb);
VOID _TuiDefWndProc_OnSetTextAlign(TWND wnd, INT align);
VOID _TuiDefWndProc_OnSetTextAttrs(TWND wnd, DWORD attrs);
LONG _TuiDefWndProc_OnEraseBk(TWND wnd, TDC dc)
{
INT i;
CHAR buf[TUI_MAX_WNDTEXT + 1];
RECT rc;
DWORD attrs = TuiGetWndTextAttrs(wnd);
if (TuiIsWndVisible(wnd))
{
TuiGetWndRect(wnd, &rc);
memset(buf, ' ', rc.cols);
buf[rc.cols] = 0;
for (i = 0; i < rc.lines; ++i)
{
TuiDrawText(dc, rc.y + i, rc.x, buf, attrs);
}
}
return TUI_OK;
}
VOID _TuiDefWndProc_OnSetText(TWND wnd, LPCSTR text)
{
LONG len = 0;
if (text)
{
len = strlen(text);
if (len > TUI_MAX_WNDTEXT)
{
strncpy(wnd->wndname, text, TUI_MAX_WNDTEXT);
}
else
{
strcpy(wnd->wndname, text);
}
}
}
LONG _TuiDefWndProc_OnGetText(TWND wnd, LPSTR text, LONG cb)
{
LONG len = strlen(wnd->wndname);
if (cb < 0 || !text)
{
return len;
}
if (cb > len)
{
cb = len;
}
memset(text, 0, cb);
strncpy(text, wnd->wndname, cb);
return strlen(text);
}
VOID _TuiDefWndProc_OnSetTextAlign(TWND wnd, INT align)
{
wnd->style &= ~(TWS_LEFT | TWS_CENTER | TWS_RIGHT);
if (ALIGN_CENTER == align)
{
wnd->style |= TWS_CENTER;
}
else if (ALIGN_RIGHT == align)
{
wnd->style |= TWS_RIGHT;
}
else
{
wnd->style |= TWS_LEFT;
}
}
VOID _TuiDefWndProc_OnSetTextAttrs(TWND wnd, DWORD attrs)
{
wnd->attrs = attrs;
}
LONG TuiDefWndProc(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_CREATE:
case TWM_KILLFOCUS:
return TUI_CONTINUE;
case TWM_ERASEBK:
{
return _TuiDefWndProc_OnEraseBk(wnd, (TDC)wparam);
}
case TWM_SETTEXT:
{
_TuiDefWndProc_OnSetText(wnd, (LPCSTR)lparam);
return 0;
}
case TWM_GETTEXT:
{
return _TuiDefWndProc_OnGetText(wnd, (LPSTR)lparam, (LONG)wparam);
}
case TWM_SETTEXTALIGN:
{
_TuiDefWndProc_OnSetTextAlign(wnd, (INT)wparam);
}
case TWM_SETTEXTATTRS:
{
_TuiDefWndProc_OnSetTextAttrs(wnd, (DWORD)wparam);
}
}
return TUI_OK;
}
UINT TuiMsgBox(TWND parent, LPCSTR caption, LPCSTR text, UINT flags)
{
MSG msg;
UINT rc = MB_INVALID;
TWND box = 0;
RECT rect;
LONG caplen = 0, textlen = 0, wndwidth = 0;
LONG nbtns = 0;
LONG btnwidth = 0;
INT i;
enum
{
Msgbox = 0,
CaptionStatic,
YesButton,
NoButton,
OKButton,
CancelButton,
EmptyCtl
};
WNDTEMPL msgbox[] =
{
{ MSGBOX, text, 0, 0, 1, 7, 1, TWS_WINDOW, 0 },
/* text */
{ STATIC, caption, MB_CAPTION, 0, 0, 1, 1, TWS_CHILD|TWS_VISIBLE|TSS_CENTER, 0 },
/* buttons */
{ BUTTON, "Yes", MB_YES, 0, 0, 1, 11, TWS_CHILD, 0 },
{ BUTTON, "No", MB_NO, 0, 0, 1, 10, TWS_CHILD, 0 },
{ BUTTON, "OK", MB_OK, 0, 0, 1, 10, TWS_CHILD, 0 },
{ BUTTON, "Cancel", MB_CANCEL, 0, 0, 1, 10, TWS_CHILD, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
/* calculate window width */
if (flags & MB_YES)
{
msgbox[YesButton].style |= TWS_VISIBLE;
++nbtns;
btnwidth += msgbox[YesButton].cols + 1;
}
else
{
msgbox[YesButton].style &= ~TWS_VISIBLE;
}
if (flags & MB_NO)
{
msgbox[NoButton].style |= TWS_VISIBLE;
++nbtns;
btnwidth += msgbox[NoButton].cols + 1;
}
else
{
msgbox[NoButton].style &= ~TWS_VISIBLE;
}
if (flags & MB_OK)
{
msgbox[OKButton].style |= TWS_VISIBLE;
++nbtns;
btnwidth += msgbox[OKButton].cols + 1;
}
else
{
msgbox[OKButton].style &= ~TWS_VISIBLE;
}
if (flags & MB_CANCEL)
{
msgbox[CancelButton].style |= TWS_VISIBLE;
btnwidth += msgbox[CancelButton].cols + 1;
++nbtns;
}
else
{
msgbox[CancelButton].style &= ~TWS_VISIBLE;
}
TuiGetWndRect(parent, &rect);
caplen = strlen(caption);
textlen = strlen(text);
wndwidth = MAX(btnwidth, MAX(caplen, textlen));
if (wndwidth % 2 == 1)
{
++wndwidth;
}
/* move window to center */
msgbox[Msgbox].lines = 7;
msgbox[Msgbox].y = rect.y + (rect.lines - msgbox[Msgbox].lines)/2;
msgbox[Msgbox].cols = wndwidth + 10;
msgbox[Msgbox].x = rect.x + (rect.cols - msgbox[Msgbox].cols)/2;
/* move caption to center */
msgbox[CaptionStatic].lines = 1;
msgbox[CaptionStatic].y = 1;
msgbox[CaptionStatic].x = 1;
msgbox[CaptionStatic].cols = msgbox[Msgbox].cols - 2;
/* move buttons to center */
if (nbtns > 3)
{
}
else if (nbtns > 0)
{
INT x = (msgbox[Msgbox].cols - btnwidth)/(nbtns == 1 ? 2 : nbtns);
for (i = YesButton; nbtns > 0 && i < EmptyCtl; ++i)
{
if (msgbox[i].style & TWS_VISIBLE)
{
/* move buttons */
msgbox[i].lines = 1;
msgbox[i].y = 5;
msgbox[i].x = x;
/* next button moved */
x += msgbox[i].cols + 1;
--nbtns;
}
}
}
box = TuiCreateWndTempl(msgbox, 0);
if (!box)
{
return -1;
}
TuiShowWnd(box, TW_SHOW);
/* remove all messages */
_TuiRemoveAllMsgs();
rc = TuiGetDlgMsgID();
while (rc == MB_INVALID)
{
TuiGetMsg(&msg);
TuiDispatchMsg(&msg);
TuiTranslateMsg(&msg);
rc = TuiGetDlgMsgID();
}
return rc;
}
UINT TuiEndDlg(TWND wnd, UINT id)
{
wnd->dlgmsgid = id;
TuiDestroyWnd(wnd);
return id;
}
/*-------------------------------------------------------------------
* File name: tdc.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* DC functions
*-----------------------------------------------------------------*/
LONG TuiPutChar(
TDC dc,
INT y,
INT x,
CHAR ch,
DWORD attrs)
{
#ifdef __USE_CURSES__
/* set attributes on */
attron(attrs);
/* print now */
mvwaddch(dc->win, y, x, ch);
/* set attributes off */
attroff(attrs);
#elif defined __USE_QIO__
/* QIO for VMS implement here */
dc->win->lType = QIO_ANY;
dc->win->cColor = 'W';
dc->win->lLength = 1;
dc->win->lRow = y;
dc->win->lColumn = x;
strcpy( dc->win->szHelp, "");
sprintf(dc->win->szText, "%c", ch);
QIO_Put();
#endif
return TUI_OK;
}
LONG TuiDrawTextEx(TDC dc, INT y, INT x, INT cols, LPCSTR text, LONG len, DWORD attrs, INT align)
{
if (DT_CENTER == align)
{
if (len)
{
return TuiDrawText(dc, y, x + (cols - len) / 2, text, attrs);
}
else
{
return TuiDrawText(dc, y, x, text, attrs);
}
}
else if (DT_RIGHT == align)
{
if (len < cols)
{
return TuiDrawText(dc, y, x + cols - len, text, attrs);
}
else
{
return TuiDrawText(dc, y, x, text, attrs);
}
}
return TuiDrawText(dc, y, x, text, attrs);
}
LONG TuiDrawText(
TDC dc,
INT y,
INT x,
LPCSTR text,
DWORD attrs)
{
#ifdef __USE_CURSES__
if (y >= LINES)
{
y = LINES - 1;
}
if (x >= COLS)
{
x = COLS - 1;
}
/* set attributes on */
attron(attrs);
/* print now */
mvwprintw(dc->win, y, x, text);
/* set attributes off */
attroff(attrs);
#elif defined __USE_QIO__
/* QIO for VMS implement here */
dc->win->lType = QIO_ANY;/*QIO_INTEGER | QIO_UPPERCASE;*/
dc->win->cColor = 'W';
dc->win->lLength = strlen(text);
dc->win->lRow = y;
dc->win->lColumn = x;
strcpy(dc->win->szHelp, "");
strcpy(dc->win->szText, text);
QIO_Put();
#endif
return TUI_OK;
}
LONG TuiMoveYX(TDC dc, INT y, INT x)
{
#ifdef __USE_CURSES__
wmove(dc->win, y, x);
#elif defined __USE_QIO__
/* QIO for VMS implement here */
dc->win->lRow = y;
dc->win->lColumn = x;
#endif
return TUI_OK;
}
LONG TuiGetYX(TDC dc, INT* y, INT* x)
{
int xx = 0, yy = 0;
#ifdef __USE_CURSES__
getyx(dc->win, yy, xx);
#elif defined __USE_QIO__
/* QIO for VMS implement here */
yy = dc->win->lRow;
xx = dc->win->lColumn;
#endif
*y = yy;
*x = xx;
return TUI_OK;
}
/*-------------------------------------------------------------------
* File name: tmsgbx.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* Message box functions
*-----------------------------------------------------------------*/
VOID TMSGB_OnPaint(TWND wnd, TDC dc);
VOID TMSGB_OnPaint(TWND wnd, TDC dc)
{
CHAR text[TUI_MAX_WNDTEXT+1];
CHAR buf[TUI_MAX_WNDTEXT+1];
RECT rc;
TuiGetWndRect(wnd, &rc);
TuiGetWndText(wnd, text, TUI_MAX_WNDTEXT);
TuiPrintTextAlignment(buf, text, rc.cols, ALIGN_CENTER);
TuiDrawText(dc, rc.y + 3, rc.x, buf, TuiGetWndTextAttrs(wnd));
}
LONG MSGBOXPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_INITDIALOG:
{
TWND btn = TuiGetFirstActiveChildWnd(wnd);
if (btn)
{
TuiSetFocus(btn);
}
#ifdef __USE_CURSES__
TuiSendMsg(wnd, TWM_SETTEXTATTRS, (WPARAM)(A_REVERSE), (LPARAM)0);
#endif
return TUI_CONTINUE;
}
case TWM_PAINT:
{
TMSGB_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
case TWM_COMMAND:
{
TuiEndDlg(wnd, (UINT)wparam);
break;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
* File name: tstc.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* STATIC functions
*-----------------------------------------------------------------*/
VOID TSTC_OnPaint(TWND wnd, TDC dc);
LONG TSTC_OnCreate(TWND wnd);
LONG STATICPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
VOID TSTC_OnPaint(TWND wnd, TDC dc)
{
CHAR buf[TUI_MAX_WNDTEXT+1];
CHAR text[TUI_MAX_WNDTEXT+1];
RECT rc;
if (TuiIsWndVisible(wnd))
{
TuiGetWndRect(wnd, &rc);
TuiGetWndText(wnd, text, TUI_MAX_WNDTEXT);
TuiPrintTextAlignment(buf, text, rc.cols, TuiGetWndStyle(wnd));
TuiDrawText(dc, rc.y, rc.x, buf, TuiGetWndTextAttrs(wnd));
}
}
LONG TSTC_OnCreate(TWND wnd)
{
#ifdef __USE_CURSES__
TuiSetWndTextAttrs(wnd, COLOR_PAIR(GREEN_BLACK));
#elif defined __USE_QIO__
TuiSetWndTextAttrs(wnd, GREEN_BLACK);
#endif
return TUI_CONTINUE;
}
LONG STATICPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_CREATE:
{
/* initial memory for static control */
return TSTC_OnCreate(wnd);
}
case TWM_DESTROY:
{
/* release memory of static control */
return 0;
}
case TWM_PAINT:
{
TSTC_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
/*-------------------------------------------------------------------
* File name: tbtn.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* BUTTON functions
*-----------------------------------------------------------------*/
struct _TBUTTONSTRUCT
{
INT state;
};
typedef struct _TBUTTONSTRUCT _TBUTTON;
typedef struct _TBUTTONSTRUCT *TBUTTON;
LONG TBTN_OnCreate(TWND wnd);
VOID TBTN_OnPaint(TWND wnd, TDC dc);
VOID TBTN_OnSetFocus(TWND wnd);
LONG TBTN_OnKillFocus(TWND wnd);
VOID TBTN_OnDestroy(TWND wnd);
VOID TBTN_OnKeyDown(TWND wnd, LONG ch);
LONG BUTTONPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
VOID TBTN_OnPaint(TWND wnd, TDC dc)
{
LONG len = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
CHAR text[TUI_MAX_WNDTEXT+1];
DWORD attrs = TuiGetWndTextAttrs(wnd);
RECT rc;
TBUTTON btn = 0;
btn = (TBUTTON)TuiGetWndParam(wnd);
TuiGetWndRect(wnd, &rc);
if (TuiIsWndVisible(wnd))
{
TuiGetWndText(wnd, text, TUI_MAX_WNDTEXT);
len = TuiPrintTextAlignment(buf,
text,
rc.cols,
ALIGN_CENTER);
if (btn->state & TBS_FOCUSED)
{
buf[0] = '[';
buf[1] = '[';
buf[len-2] = ']';
buf[len-1] = ']';
}
else
{
buf[0] = '[';
buf[1] = ' ';
buf[len-2] = ' ';
buf[len-1] = ']';
}
if (!TuiIsWndEnabled(wnd))
{
#ifdef __USE_CURSES__
attrs = A_DIM|A_NORMAL;
#elif defined __USE_QIO__
attrs = 0;
#endif
}
else if (btn->state == TBS_RELEASED)
{
#ifdef __USE_CURSES__
attrs = A_REVERSE;
#elif defined __USE_QIO__
attrs = 0;
#endif
}
TuiDrawText(dc, rc.y, rc.x, buf, attrs);
}
TuiMoveYX(dc, rc.y, rc.x);
}
LONG TBTN_OnCreate(TWND wnd)
{
TBUTTON btn = 0;
/* initial memory for static control */
btn = (TBUTTON)malloc(sizeof(_TBUTTON));
if (!btn)
{
return TUI_ERROR;
}
btn->state = TBS_RELEASED;
TuiSetWndParam(wnd, (LPVOID)btn);
#ifdef __USE_CURSES__
TuiSetWndTextAttrs(wnd, COLOR_PAIR(CYAN_BLACK));
#elif defined __USE_QIO__
TuiSetWndTextAttrs(wnd, CYAN_BLACK);
#endif
return TUI_CONTINUE;
}
VOID TBTN_OnSetFocus(TWND wnd)
{
NMHDR nmhdr;
TBUTTON btn = (TBUTTON)TuiGetWndParam(wnd);
btn->state = TBS_FOCUSED; /* add state */
TuiInvalidateWnd(wnd);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TBN_SETFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
}
LONG TBTN_OnKillFocus(TWND wnd)
{
NMHDR nmhdr;
LONG rc = TUI_CONTINUE;
TBUTTON btn = (TBUTTON)TuiGetWndParam(wnd);
btn->state &= ~TBS_FOCUSED; /* remove state */
TuiInvalidateWnd(wnd);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TBN_KILLFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
return rc;
}
VOID TBTN_OnDestroy(TWND wnd)
{
TBUTTON btn = (TBUTTON)TuiGetWndParam(wnd);
free(btn);
}
VOID TBTN_OnKeyDown(TWND wnd, LONG ch)
{
TBUTTON btn = (TBUTTON)TuiGetWndParam(wnd);
INT repaint = 0;
switch (ch)
{
case TVK_SPACE:
repaint = 1;
break;
}
if (repaint)
{
btn->state = TBS_PRESSED;
TuiInvalidateWnd(wnd);
btn->state = TBS_RELEASED | TBS_FOCUSED;
TuiInvalidateWnd(wnd);
/* send notification */
TuiPostMsg(TuiGetParent(wnd),
TWM_COMMAND,
(WPARAM)TuiGetWndID(wnd),
(LPARAM)wnd);
}
}
LONG BUTTONPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_CREATE:
{
/* initial memory for static control */
return TBTN_OnCreate(wnd);
}
case TWM_DESTROY:
{
/* release memory of static control */
TBTN_OnDestroy(wnd);
return 0;
}
case TWM_SETFOCUS:
{
TBTN_OnSetFocus(wnd);
break;
}
case TWM_KILLFOCUS:
{
return TBTN_OnKillFocus(wnd);
}
case TWM_KEYDOWN:
{
TBTN_OnKeyDown(wnd, (LONG)wparam);
break;
}
case TWM_PAINT:
{
TBTN_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
/*-------------------------------------------------------------------
* File name: tedt.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* EDIT functions
*-----------------------------------------------------------------*/
struct _TEDITSTRUCT
{
CHAR editbuf[TUI_MAX_WNDTEXT+1];
INT firstvisit;
CHAR passchar;
INT showpass;
INT firstchar;
INT limitchars;
INT editing;
INT decwidth;
};
typedef struct _TEDITSTRUCT _TEDIT;
typedef struct _TEDITSTRUCT *TEDIT;
LONG TEDT_OnCreate(TWND wnd);
VOID TEDT_OnDestroy(TWND wnd);
VOID TEDT_OnSetFocus(TWND wnd);
LONG TEDT_OnKillFocus(TWND wnd);
LONG TEDT_ValidateNumberStyle(TWND wnd, TEDIT edit, LONG ch);
LONG TEDT_ValidateDecimalStyle(TWND wnd, TEDIT edit, LONG ch);
VOID TEDT_OnChar(TWND wnd, LONG ch);
VOID TEDT_OnPaint(TWND wnd, TDC dc);
VOID TEDT_OnLimitText(TWND wnd, INT limit);
VOID TEDT_OnSetPasswdChar(TWND wnd, CHAR passchar);
VOID TEDT_OnShowPasswdChar(TWND wnd, INT show);
VOID TEDT_OnSetDecWidth(TWND wnd, INT width);
LONG EDITPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
LONG TEDT_OnCreate(TWND wnd)
{
TEDIT edit = 0;
DWORD style = TuiGetWndStyle(wnd);
RECT rc;
/* initial memory for edit control */
edit = (TEDIT)malloc(sizeof(_TEDIT));
if (!edit)
{
return TUI_MEM;
}
TuiGetWndRect(wnd, &rc);
TuiGetWndText(wnd, edit->editbuf, TUI_MAX_WNDTEXT);
edit->firstvisit = 1;
edit->firstchar = 0;
edit->passchar = '*';
edit->showpass = TW_SHOW;
edit->editing = 0;
edit->decwidth = 6;
edit->limitchars = (TES_AUTOHSCROLL & style ? TUI_MAX_WNDTEXT : rc.cols);
TuiSetWndParam(wnd, (LPVOID)edit);
#ifdef __USE_CURSES__
TuiSetWndTextAttrs(wnd, COLOR_PAIR(CYAN_BLACK));
#elif defined __USE_QIO__
TuiSetWndTextAttrs(wnd, CYAN_BLACK);
#endif
return TUI_CONTINUE;
}
VOID TEDT_OnDestroy(TWND wnd)
{
TEDIT edit = 0;
/* release memory of edit control */
edit = (TEDIT)TuiGetWndParam(wnd);
free(edit);
}
VOID TEDT_OnSetFocus(TWND wnd)
{
TEDIT edit = 0;
NMHDR nmhdr;
/* save edited buffer */
edit = (TEDIT)TuiGetWndParam(wnd);
TuiGetWndText(wnd, edit->editbuf, TUI_MAX_WNDTEXT);
edit->firstvisit = 1;
edit->firstchar = 0;
edit->editing = 0;
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TEN_SETFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
}
LONG TEDT_OnKillFocus(TWND wnd)
{
TEDIT edit = 0;
NMHDR nmhdr;
LONG rc = TUI_CONTINUE;
CHAR buf[TUI_MAX_WNDTEXT + 1];
DOUBLE decimal = 0.0;
DWORD style = TuiGetWndStyle(wnd);
edit = (TEDIT)TuiGetWndParam(wnd);
rc = TuiIsWndValidate(wnd, buf);
if (rc != TUI_CONTINUE)
{
return rc;
}
/* check if style is TES_DECIMAL */
if (style & TES_DECIMAL)
{
decimal = atof(edit->editbuf);
sprintf(buf, "%.*f", edit->decwidth, decimal);
strcpy(edit->editbuf, buf);
}
/* update text */
edit->firstchar = 0;
edit->editing = 0;
TuiSetWndText(wnd, edit->editbuf);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TEN_KILLFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
TuiInvalidateWnd(wnd);
return rc;
}
LONG TEDT_ValidateNumberStyle(TWND wnd, TEDIT edit, LONG ch)
{
LONG rc = TUI_CONTINUE;
if (ch < '0' || ch > '9')
{
rc = TUI_ERROR;
}
return rc;
}
LONG TEDT_ValidateDecimalStyle(TWND wnd, TEDIT edit, LONG ch)
{
LONG rc = TUI_CONTINUE;
CHAR* decimal = strchr(edit->editbuf, '.');
LONG len = strlen(edit->editbuf);
/* not allowed '-' in the string */
if ((len > 0 && (edit->firstvisit == 0)) && ch == '-')
{
rc = TUI_ERROR;
}
if ((rc == TUI_CONTINUE) && (len == 0 || (edit->firstvisit == 1)) && ch == '-')
{
/* ok */
}
else if (ch == '.')
{
if (decimal)
{
/* not allowed having '.' more than one */
rc = TUI_ERROR;
}
}
else if (ch < '0' || ch > '9')
{
rc = TUI_ERROR;
}
else
{
}
return rc;
}
VOID TEDT_OnChar(TWND wnd, LONG ch)
{
TEDIT edit = 0;
NMHDR nmhdr;
INT changed = 0;
TDC dc = TuiGetDC(wnd);
LONG len = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
DWORD attrs = TuiGetWndTextAttrs(wnd);
CHAR text[TUI_MAX_WNDTEXT+1];
DWORD style = TuiGetWndStyle(wnd);
RECT rc;
LONG ret = TUI_CONTINUE;
edit = (TEDIT)TuiGetWndParam(wnd);
if (TuiIsWndEnabled(wnd))
{
#ifdef __USE_CURSES__
attrs |= A_UNDERLINE;
#elif defined __USE_QIO__
attrs |= 0;
#endif
}
TuiGetWndText(wnd, text, TUI_MAX_WNDTEXT);
TuiGetWndRect(wnd, &rc);
if (ch == TVK_ESCAPE)
{
if (edit->firstvisit == 0)
{
edit->firstvisit = 1;
strcpy(edit->editbuf, text);
edit->firstchar = 0;
edit->editing = 0;
TuiInvalidateWnd(wnd);
return;
}
}
if (ch >= 0x20 && ch < 0x7f)
{
/* add char */
len = strlen(edit->editbuf);
if (len + 1 <= edit->limitchars)
{
if (TES_NUMBER & style)
{
/* require only number input */
ret = TEDT_ValidateNumberStyle(wnd, edit, ch);
if (ret != TUI_CONTINUE)
{
return;
}
}
else if (TES_DECIMAL & style)
{
/* require only decimal input */
ret = TEDT_ValidateDecimalStyle(wnd, edit, ch);
if (ret != TUI_CONTINUE)
{
return;
}
}
else if (TES_UPPERCASE & style)
{
/* require changing from small to CAPITAL */
if (ch >= 'a' && ch <= 'z')
{
ch = ch - 'a' + 'A';
}
}
else if (TES_LOWERCASE & style)
{
if (ch >= 'A' && ch <= 'Z')
{
ch = ch - 'A' + 'a';
}
}
if (edit->firstvisit == 1)
{
edit->firstvisit = 0;
if (!(TES_APPENDMODE & style) || (TES_PASSWORD & style)) /* replace mode */
{
edit->editbuf[0] = 0;
memset(buf, ' ', rc.cols);
buf[rc.cols] = 0;
TuiDrawText(dc, rc.y, rc.x, buf, attrs);
TuiMoveYX(dc, rc.y, rc.x);
}
else if (TES_AUTOHSCROLL & style)
{
/* show first char at */
if (len > rc.cols)
{
edit->firstchar = len - rc.cols - 1;
}
}
}
/* append a new char */
len = strlen(edit->editbuf);
if (len < edit->limitchars)
{
edit->editbuf[len] = ch;
edit->editbuf[len+1] = 0;
if (len < rc.cols)
{
if (TES_PASSWORD & style)
{
if (edit->showpass == TW_SHOW)
{
TuiPutChar(dc, rc.y, rc.x + len,
edit->passchar,
attrs);
}
}
else
{
TuiPutChar(dc, rc.y, rc.x + len,
ch,
attrs);
}
}
changed = 1;
} /* len < limit */
if (TES_AUTOHSCROLL & style)
{
len = strlen(edit->editbuf);
if (len <= edit->limitchars && len > rc.cols && changed)
{
++edit->firstchar;
if (edit->firstchar > edit->limitchars - rc.cols)
{
edit->firstchar = edit->limitchars - rc.cols - 1;
}
TuiInvalidateWnd(wnd);
if ((TES_PASSWORD & style) && (edit->showpass == TW_SHOW))
{
TuiMoveYX(dc, rc.y, rc.x);
}
else
{
TuiMoveYX(dc, rc.y, rc.x + rc.cols);
}
}
}
/* editing */
edit->editing = 1;
} /*TUI_MAX_WNDTEXT*/
}
else if (ch == 0x7f || ch == TVK_DELETE ||
#ifdef __USE_CURSES__
ch == KEY_BACKSPACE) /* delete char */
#elif defined __USE_QIO__
ch == KEY_BS)
#endif
{
len = strlen(edit->editbuf);
if (edit->firstvisit == 1)
{
edit->firstvisit = 0;
if (!(TES_APPENDMODE & style) || TES_PASSWORD & style) /* replace mode */
{
edit->editbuf[0] = 0;
sprintf(buf, "%*s", rc.cols, " ");
TuiMoveYX(dc, rc.y, rc.x);
TuiDrawText(dc, rc.y, rc.x, buf, attrs);
}
else if (TES_AUTOHSCROLL & style)
{
/* show first char at */
if (len > rc.cols)
{
edit->firstchar = len - rc.cols - 1;
}
}
}
if (len > 0)
{
if (len > rc.cols)
{
TuiPutChar(dc, rc.y, rc.x + rc.cols - 1, ' ', attrs);
}
else
{
TuiPutChar(dc, rc.y, rc.x + len - 1, ' ', attrs);
}
TuiMoveYX(dc, rc.y, rc.x + len - 1);
edit->editbuf[len - 1] = 0;
changed = 1;
if (TES_AUTOHSCROLL & style)
{
len = strlen(edit->editbuf);
if (len >= rc.cols)
{
edit->firstchar = len - rc.cols;
if (edit->firstchar < 0)
{
edit->firstchar = 0;
}
len = rc.cols;
}
else
{
edit->firstchar = 0;
}
TuiInvalidateWnd(wnd);
TuiMoveYX(dc, rc.y, rc.x + len);
}
}
/* editing */
edit->editing = 1;
}
if (changed)
{
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TEN_CHANGED;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
}
}
VOID TEDT_OnPaint(TWND wnd, TDC dc)
{
TEDIT edit = 0;
LONG len = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
CHAR text[TUI_MAX_WNDTEXT+1];
DWORD attrs = TuiGetWndTextAttrs(wnd);
RECT rc;
DWORD style = TuiGetWndStyle(wnd);
edit = (TEDIT)TuiGetWndParam(wnd);
if (TuiIsWndEnabled(wnd))
{
#ifdef __USE_CURSES__
attrs |= A_UNDERLINE;
#elif defined __USE_QIO__
attrs |= 0;
#endif
}
TuiGetWndRect(wnd, &rc);
len = rc.cols;
if (TES_PASSWORD & style)
{
if (edit->showpass == TW_SHOW)
{
memset(buf, edit->passchar, len);
}
else
{
memset(buf, ' ', len);
}
buf[len] = 0;
TuiDrawText(dc, rc.y, rc.x, buf, attrs);
return;
}
if (TuiIsWndVisible(wnd))
{
len = MIN(strlen(edit->editbuf), rc.cols);
memset(buf, 0, TUI_MAX_WNDTEXT);
memcpy(buf, &edit->editbuf[edit->firstchar], len);
if (edit->editing)
{
TuiPrintTextAlignment(text, buf, rc.cols, ALIGN_LEFT);
}
else
{
TuiPrintTextAlignment(text, buf, rc.cols, style);
}
TuiDrawText(dc, rc.y, rc.x, text, attrs);
}
TuiMoveYX(dc, rc.y, rc.x);
}
VOID TEDT_OnLimitText(TWND wnd, INT limit)
{
TEDIT edit = 0;
CHAR text[TUI_MAX_WNDTEXT + 1];
if (limit > 0 || limit <= TUI_MAX_WNDTEXT)
{
edit = (TEDIT)TuiGetWndParam(wnd);
edit->limitchars = limit;
TuiGetWndText(wnd, text, TUI_MAX_WNDTEXT);
if (strlen(text) > limit)
{
text[limit] = 0;
TuiSetWndText(wnd, text);
strcpy(edit->editbuf, text);
}
}
}
VOID TEDT_OnSetPasswdChar(TWND wnd, CHAR passchar)
{
TEDIT edit = 0;
edit = (TEDIT)TuiGetWndParam(wnd);
edit->passchar = passchar;
}
VOID TEDT_OnShowPasswdChar(TWND wnd, INT show)
{
TEDIT edit = 0;
edit = (TEDIT)TuiGetWndParam(wnd);
edit->showpass = (show == TW_SHOW ? TW_SHOW : TW_HIDE);
}
VOID TEDT_OnSetDecWidth(TWND wnd, INT width)
{
TEDIT edit = 0;
edit = (TEDIT)TuiGetWndParam(wnd);
edit->decwidth = width;
}
LONG EDITPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_CREATE:
{
return TEDT_OnCreate(wnd);
}
case TWM_DESTROY:
{
TEDT_OnDestroy(wnd);
return 0;
}
case TWM_SETFOCUS:
{
TEDT_OnSetFocus(wnd);
break;
}
case TWM_KILLFOCUS:
{
return TEDT_OnKillFocus(wnd);
}
case TWM_CHAR:
{
TEDT_OnChar(wnd, (LONG)wparam);
break;
}
case TWM_PAINT:
{
TEDT_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
case TEM_LIMITTEXT:
{
TEDT_OnLimitText(wnd, (INT)wparam);
return 0;
}
case TEM_SETPASSWDCHAR:
{
TEDT_OnSetPasswdChar(wnd, (CHAR)wparam);
return 0;
}
case TEM_SETDECWIDTH:
{
TEDT_OnSetDecWidth(wnd, (INT)wparam);
return 0;
}
case TEM_SHOWPASSWDCHAR:
{
TEDT_OnShowPasswdChar(wnd, (INT)wparam);
return 0;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
/*-------------------------------------------------------------------
* File name: tlb.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* LISTBOX functions
*-----------------------------------------------------------------*/
struct _TLISTBOXITEMSTRUCT
{
CHAR itemtext[TUI_MAX_WNDTEXT+1];
LPVOID data;
INT checked;
struct _TLISTBOXITEMSTRUCT *prev;
struct _TLISTBOXITEMSTRUCT *next;
};
typedef struct _TLISTBOXITEMSTRUCT tlistbox_t;
struct _TUILISTBOXSTRUCT
{
INT firstvisible;
INT nitems; /* item counts */
INT cursel; /* highlight item */
tlistbox_t* firstitem; /* always be item id = 0 if it is existing */
tlistbox_t* lastitem;
tlistbox_t* selitem; /* must be the same cursel item */
tlistbox_t* firstvisibleitem;
INT checkeditems; /* count item checked */
tlistbox_t* lastitemchecked; /* to identify the last item checked */
};
typedef struct _TUILISTBOXSTRUCT _TLISTBOX;
typedef struct _TUILISTBOXSTRUCT *TLISTBOX;
tlistbox_t* _TLB_FindItemByIndex(TWND wnd, INT idx);
INT TLB_OnCountItemCheck(TWND wnd);
INT TLB_OnGetItemChecked(TWND wnd, INT idx);
INT TLB_OnSetItemChecked(TWND wnd, INT idx, INT check);
LPVOID TLB_OnGetItemData(TWND wnd, INT idx);
VOID TLB_OnSetItemData(TWND wnd, INT idx, LPVOID data);
VOID TLB_OnSetCurSel(TWND wnd, INT idx);
LONG TLB_OnGetItemCount(TWND wnd);
VOID TLB_OnSetItemText(TWND wnd, INT idx, LPSTR text);
LONG TLB_OnGetItemText(TWND wnd, INT idx, LPSTR text);
INT TLB_OnGetCurSel(TWND wnd);
VOID TLB_OnDeleteAllItems(TWND wnd);
VOID TLB_OnDeleteItem(TWND wnd, LONG idx);
LONG TLB_OnAddItem(TWND wnd, LPCSTR text);
VOID TLB_OnPaint(TWND wnd, TDC dc);
VOID TLB_OnKeyDown(TWND wnd, LONG ch);
LONG TLB_OnKillFocus(TWND wnd);
VOID TLB_OnSetFocus(TWND wnd);
VOID TLB_OnDestroy(TWND wnd);
LONG TLB_OnCreate(TWND wnd);
LONG LISTBOXPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
tlistbox_t* _TLB_FindItemByIndex(TWND wnd, INT idx)
{
TLISTBOX lb = 0;
INT i = 0;
tlistbox_t* item = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
if (idx < 0 || idx >= lb->nitems)
{
return 0;
}
item = lb->firstitem;
for (i = 0; i < lb->nitems && item; ++i, item = item->next)
{
if (i == idx)
{
return item;
}
}
return 0;
}
LONG TLB_OnCreate(TWND wnd)
{
TLISTBOX lb = 0;
/* initial memory for static control */
lb = (TLISTBOX)malloc(sizeof(_TLISTBOX));
if (!lb)
{
return TUI_ERROR;
}
lb->firstvisible = -1;
lb->cursel = -1;
lb->nitems = 0;
lb->firstitem = 0;
lb->lastitem = 0;
lb->selitem = 0;
lb->firstvisibleitem = 0;
lb->checkeditems = 0;
lb->lastitemchecked = 0;
TuiSetWndParam(wnd, (LPVOID)lb);
#ifdef __USE_CURSES__
TuiSetWndTextAttrs(wnd, COLOR_PAIR(YELLOW_BLUE));
#elif defined __USE_QIO__
TuiSetWndTextAttrs(wnd, YELLOW_BLUE);
#endif
return TUI_CONTINUE;
}
VOID TLB_OnDestroy(TWND wnd)
{
TLISTBOX lb = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
/* release memory of static control */
TLB_DeleteAllItems(wnd);
free(lb);
}
VOID TLB_OnSetFocus(TWND wnd)
{
TLISTBOX lb = 0;
NMHDR nmhdr;
lb = (TLISTBOX)TuiGetWndParam(wnd);
if (lb->cursel >= lb->nitems)
{
lb->cursel = 0;
}
else if (lb->cursel < 0)
{
lb->cursel = 0;
}
TuiInvalidateWnd(wnd);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TLBN_SETFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
}
LONG TLB_OnKillFocus(TWND wnd)
{
NMHDR nmhdr;
LONG rc = TUI_CONTINUE;
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TLBN_KILLFOCUS;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
return rc;
}
VOID TLB_OnKeyDown(TWND wnd, LONG ch)
{
TLISTBOX lb = 0;
NMHDR nmhdr;
INT repaint = 0;
DWORD style = TuiGetWndStyle(wnd);
INT lines = 0;
RECT rc;
lb = (TLISTBOX)TuiGetWndParam(wnd);
TuiGetWndRect(wnd, &rc);
switch (ch)
{
case TVK_SPACE:
{
if ((style & TLBS_CHECKBOX) ||
(style & TLBS_RADIOBOX))
{
/* get current and check it */
TLB_SetItemChecked(wnd, lb->cursel, LB_CHECKED);
}
++repaint;
break;
}
case KEY_DOWN:
case KEY_RIGHT:
{
++lines;
++repaint;
break;
}
case KEY_UP:
case KEY_LEFT:
{
--lines;
++repaint;
break;
}
case TVK_PRIOR:
#ifdef __USE_CURSES__
case KEY_PPAGE:
#elif (defined __USE_QIO__ && defined __VMS__)
case KEY_PREV:
#endif
{
lines -= rc.lines;
++repaint;
break;
}
case TVK_NEXT:
#ifdef __USE_CURSES__
case KEY_NPAGE:
#elif (defined __USE_QIO__ && defined __VMS__)
case KEY_NEXT:
#endif
{
lines += rc.lines;
++repaint;
break;
}
}
if (repaint)
{
lb->cursel += lines;
if (lb->cursel >= lb->nitems)
{
lb->cursel = lb->nitems - 1;
}
else if (lb->cursel < 0)
{
lb->cursel = 0;
}
/* find the new first visible */
if (lb->cursel >= lb->firstvisible + rc.lines)
{
lb->firstvisible += lines;
if (lb->firstvisible > lb->nitems - rc.lines)
{
lb->firstvisible = lb->nitems - rc.lines;
}
}
else if (lb->firstvisible > lb->cursel)
{
lb->firstvisible += lines;
if (lb->firstvisible < 0)
{
lb->firstvisible = 0;
}
}
TuiInvalidateWnd(wnd);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TLBN_SELCHANGED;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
}
lb->selitem = _TLB_FindItemByIndex(wnd, lb->cursel);
lb->firstvisibleitem = _TLB_FindItemByIndex(wnd, lb->firstvisible);
}
VOID TLB_OnPaint(TWND wnd, TDC dc)
{
TLISTBOX lb = 0;
INT i = 0;
tlistbox_t* item = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
CHAR text[TUI_MAX_WNDTEXT+1];
DWORD attrs = TuiGetWndTextAttrs(wnd);
DRAWITEM di;
RECT rc;
DWORD style = TuiGetWndStyle(wnd);
if (!TuiIsWndVisible(wnd))
{
return;
}
lb = (TLISTBOX)TuiGetWndParam(wnd);
/* draw */
if (lb->nitems > 0)
{
item = lb->firstitem;
TuiGetWndRect(wnd, &rc);
for (i = 0; i < lb->nitems && item; ++i, item = item->next)
{
if (i < lb->firstvisible)
{
/* do nothing */
continue;
}
else if (i - lb->firstvisible < rc.lines)
{
if (style & TLBS_OWNERDRAW)
{
memset(&di, 0, sizeof(DRAWITEM));
di.rcitem.y = rc.y + (i - lb->firstvisible);
di.rcitem.x = rc.x;
di.rcitem.lines = 1;
di.rcitem.cols = rc.cols;
di.idx = i;
TuiSendMsg(TuiGetParent(wnd), TWM_DRAWITEM, (WPARAM)i, (LPARAM)&di);
}
else
{
strcpy(text, "");
if (style & TLBS_CHECKBOX)
{
if (item->checked)
{
strcpy(text, "[X] ");
}
else
{
strcpy(text, "[ ] ");
}
}
else if (style & TLBS_RADIOBOX)
{
if (item->checked)
{
strcpy(text, "(*) ");
}
else
{
strcpy(text, "( ) ");
}
}
/* copy from item text */
strcat(text, item->itemtext);
TuiPrintTextAlignment(buf, text, rc.cols, style);
TuiDrawText(dc,
rc.y+(i-lb->firstvisible),
rc.x,
buf,
#ifdef __USE_CURSES__
(i == lb->cursel ? A_REVERSE|attrs : attrs));
#elif defined __USE_QIO__
0); /* highlight */
#endif
}
}/* not owner draw */
} /* for each item */
} /* items are valid */
}
LONG TLB_OnAddItem(TWND wnd, LPCSTR text)
{
TLISTBOX lb = 0;
LONG len = 0;
tlistbox_t* item = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
item = (tlistbox_t*)malloc(sizeof(tlistbox_t));
if (item)
{
memset(item, 0, sizeof(tlistbox_t));
len = strlen(text);
if (len > TUI_MAX_WNDTEXT)
{
len = TUI_MAX_WNDTEXT;
}
strncpy(item->itemtext, text, len);
if (lb->firstitem)
{
item->prev = lb->lastitem;
lb->lastitem->next = item;
lb->lastitem = item;
}
else
{
lb->firstitem = lb->lastitem = item;
lb->firstvisible = 0;
}
++lb->nitems;
return lb->nitems;
}
return TUI_MEM;
}
VOID TLB_OnDeleteItem(TWND wnd, LONG idx)
{
TLISTBOX lb = 0;
tlistbox_t* item = 0;
tlistbox_t* nextitem = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
/* remove the links */
nextitem = item->next;
if (nextitem)
{
nextitem->prev = item->prev;
}
if (item->prev)
{
item->prev->next = nextitem;
}
/* check if removed item is the first item or the last item */
if (item == lb->firstitem)
{
lb->firstitem = nextitem;
}
else if (item == lb->lastitem)
{
lb->lastitem = item->prev;
}
/* free the memory */
item->next = item->prev = 0;
free(item);
/* decrement items */
--lb->nitems;
if (lb->cursel >= lb->nitems)
{
lb->cursel = lb->nitems - 1;
}
}
}
VOID TLB_OnDeleteAllItems(TWND wnd)
{
TLISTBOX lb = 0;
INT nitems = 0;
INT i = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
nitems = lb->nitems;
for (i = 0; i < nitems; ++i)
{
TuiPostMsg(wnd, TLBM_DELETEITEM, 0, 0);
}
}
INT TLB_OnGetCurSel(TWND wnd)
{
TLISTBOX lb = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
return lb->cursel;
}
LONG TLB_OnGetItemText(TWND wnd, INT idx, LPSTR text)
{
tlistbox_t* item = 0;
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
strcpy(text, item->itemtext);
}
return strlen(text);
}
VOID TLB_OnSetItemText(TWND wnd, INT idx, LPSTR text)
{
tlistbox_t* item = 0;
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
strcpy(item->itemtext, text);
}
}
LONG TLB_OnGetItemCount(TWND wnd)
{
TLISTBOX lb = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
return lb->nitems;
}
VOID TLB_OnSetCurSel(TWND wnd, INT idx)
{
TLISTBOX lb = 0;
NMHDR nmhdr;
RECT rc;
lb = (TLISTBOX)TuiGetWndParam(wnd);
if (idx < 0 || idx >= lb->nitems)
{
idx = -1;
}
lb->cursel = idx;
if (lb->cursel >= 0)
{
lb->firstvisible = lb->cursel;
TuiGetWndRect(wnd, &rc);
if (lb->firstvisible + rc.lines > lb->nitems)
{
lb->firstvisible = lb->nitems - rc.lines;
}
}
else
{
lb->firstvisible = 0;
}
TuiInvalidateWnd(wnd);
/* send notification */
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TLBN_SELCHANGED;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
lb->selitem = _TLB_FindItemByIndex(wnd, lb->cursel);
lb->firstvisibleitem = _TLB_FindItemByIndex(wnd, lb->firstvisible);
}
VOID TLB_OnSetItemData(TWND wnd, INT idx, LPVOID data)
{
tlistbox_t* item = 0;
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
item->data = data;
}
}
LPVOID TLB_OnGetItemData(TWND wnd, INT idx)
{
tlistbox_t* item = 0;
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
return item->data;
}
return 0;
}
INT TLB_OnSetItemChecked(TWND wnd, INT idx, INT check)
{
tlistbox_t* item = 0;
TLISTBOX lb = 0;
DWORD style = TuiGetWndStyle(wnd);
lb = (TLISTBOX)TuiGetWndParam(wnd);
item = _TLB_FindItemByIndex(wnd, idx);
/* found and do the check item state */
if (item)
{
if (check == LB_UNCHECKED)
{
--lb->checkeditems;
if (lb->checkeditems < 0)
{
lb->checkeditems = 0;
lb->lastitemchecked = 0;
}
item->checked = LB_UNCHECKED;
}
else
{
/* unselected the last if it is radio style */
if (style & TLBS_RADIOBOX)
{
if (lb->lastitemchecked)
{
lb->lastitemchecked->checked = LB_UNCHECKED;
}
}
else if (style & TLBS_CHECKBOX)
{
if (item->checked == LB_CHECKED)
{
--lb->checkeditems;
if (lb->checkeditems < 0)
{
lb->checkeditems = 0;
lb->lastitemchecked = 0;
}
item->checked = LB_UNCHECKED;
return LB_OK;
}
}
/* count checked item */
++lb->checkeditems;
if (lb->checkeditems > lb->nitems)
{
lb->checkeditems = lb->nitems;
}
/* checked and save the last checked item */
item->checked = LB_CHECKED;
lb->lastitemchecked = item;
}
return LB_OK;
}
return LB_ERROR;
}
INT TLB_OnGetItemChecked(TWND wnd, INT idx)
{
tlistbox_t* item = 0;
item = _TLB_FindItemByIndex(wnd, idx);
if (item)
{
return item->checked;
}
return LB_ERROR;
}
INT TLB_OnCountItemCheck(TWND wnd)
{
TLISTBOX lb = 0;
lb = (TLISTBOX)TuiGetWndParam(wnd);
return lb->checkeditems;
}
LONG LISTBOXPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TLBM_COUNTITEMCHECKED:
{
return TLB_OnCountItemCheck(wnd);
}
case TLBM_GETITEMCHECKED:
{
return TLB_OnGetItemChecked(wnd, (INT)wparam);
}
case TLBM_SETITEMCHECKED:
{
return TLB_OnSetItemChecked(wnd, (INT)wparam, (INT)lparam);
}
case TWM_CREATE:
{
return TLB_OnCreate(wnd);
}
case TWM_DESTROY:
{
TLB_OnDestroy(wnd);
return 0;
}
case TWM_SETFOCUS:
{
TLB_OnSetFocus(wnd);
break;
}
case TWM_KILLFOCUS:
{
return TLB_OnKillFocus(wnd);
}
case TWM_KEYDOWN:
{
TLB_OnKeyDown(wnd, (LONG)wparam);
break;
}
case TWM_PAINT:
{
TLB_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
case TLBM_ADDITEM:
{
return TLB_OnAddItem(wnd, (LPCSTR)lparam);
}
case TLBM_DELETEITEM:
{
TLB_OnDeleteItem(wnd, (LONG)wparam);
return 0;
}
case TLBM_GETCURSEL:
{
return TLB_OnGetCurSel(wnd);
}
case TLBM_SETCURSEL:
{
TLB_OnSetCurSel(wnd, (INT)wparam);
return 0;
}
case TLBM_DELETEALLITEMS:
{
TLB_OnDeleteAllItems(wnd);
return 0;
}
case TLBM_GETITEMCOUNT:
{
return TLB_OnGetItemCount(wnd);
}
case TLBM_SETITEMDATA:
{
TLB_OnSetItemData(wnd, (INT)wparam, (LPVOID)lparam);
return 0;
}
case TLBM_GETITEMDATA:
{
return (LONG)TLB_OnGetItemData(wnd, (INT)wparam);
}
case TLBM_SETITEMTEXT:
{
TLB_OnSetItemText(wnd, (INT)wparam, (LPSTR)lparam);
return 0;
}
case TLBM_GETITEMTEXT:
{
return TLB_OnGetItemText(wnd, (INT)wparam, (LPSTR)lparam);
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
/*-------------------------------------------------------------------
* File name: tlctl.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#ifdef __USE_CURSES__
#include <curses.h>
#elif (defined __USE_QIO__ && defined __VMS__)
#include <qio_init.h>
#endif
#include "tui.h"
/*-------------------------------------------------------------------
* LISTCTRL functions
*-----------------------------------------------------------------*/
struct _TLISTCELLSTRUCT
{
INT y;
INT x;
CHAR caption[TUI_MAX_WNDTEXT+1];
DWORD attrs;
VOID* data;
struct _TLISTCELLSTRUCT *prev;
struct _TLISTCELLSTRUCT *next;
};
typedef struct _TLISTCELLSTRUCT tlistcell_t;
struct _THEADERSTRUCT
{
INT id;
CHAR caption[TUI_MAX_WNDTEXT+1];
INT cols; /* width */
INT align; /* left is a default */
DWORD attrs;
tlistcell_t* firstcell;
tlistcell_t* lastcell;
struct _THEADERSTRUCT *prev;
struct _THEADERSTRUCT *next;
};
typedef struct _THEADERSTRUCT theader_t;
struct _TLISTCTRLSTRUCT
{
theader_t* firsthdr;
theader_t* lasthdr;
theader_t* firstvisiblehdr;
theader_t* lastvisiblehdr;
INT nheaders;
INT nitems;
INT hdrids; /* header id */
INT hdrallwidths;
/* item control */
INT curselrow;
INT curselcol;
INT firstvisibleitem;
TWND editbox;
};
typedef struct _TLISTCTRLSTRUCT _TLISTCTRL;
typedef struct _TLISTCTRLSTRUCT *TLISTCTRL;
theader_t* _TLCTL_FindHeaderByIndex(TLISTCTRL lctl, INT col);
tlistcell_t* _TLCTL_FindCellByIndex(TLISTCTRL lctl, INT col, INT idx);
tlistcell_t* _TLCTL_FindCellByHeader(TLISTCTRL lctl, theader_t* header, INT idx);
LONG _TLCTL_GetCellRect(TLISTCTRL lctl, INT col, INT idx, RECT* rect);
LONG LISTCTRLPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
VOID TLCTL_OnKeyDown(TWND wnd, LONG ch);
VOID TLCTL_OnPaint(TWND wnd, TDC dc);
LONG TLCTL_OnAddItem(TWND wnd, LPSTR text, INT nitems);
VOID TLCTL_OnDeleteAllItems(TWND wnd);
VOID TLCTL_OnDeleteColumn(TWND wnd, INT col);
LONG TLCTL_OnAddColumn(TWND wnd, HEADERITEM* hdritem);
VOID TLCTL_OnDestroy(TWND wnd);
LONG TLCTL_OnCreate(TWND wnd);
LONG TLCTL_OnGetItem(TWND wnd, UINT flags, SUBITEM* subitem);
LONG TLCTL_OnSetItem(TWND wnd, UINT flags, SUBITEM* subitem);
theader_t* _TLCTL_FindHeaderByIndex(TLISTCTRL lctl, INT col)
{
theader_t* header = 0;
INT i;
if (col < 0 || col >= lctl->nheaders)
{
return 0; /* no header deleted */
}
header = lctl->firsthdr;
for (i = 0; i == col && i < lctl->nheaders; ++i)
{
header = header->next;
}
return header;
}
tlistcell_t* _TLCTL_FindCellByIndex(TLISTCTRL lctl, INT col, INT idx)
{
tlistcell_t* cell = 0;
theader_t* header = 0;
INT i;
if (idx < 0 || idx >= lctl->nitems)
{
return 0;
}
header = _TLCTL_FindHeaderByIndex(lctl, col);
if (header)
{
cell = header->firstcell;
for (i = 0; i == idx && i < lctl->nitems; ++i)
{
cell = cell->next;
}
}
return cell;
}
tlistcell_t* _TLCTL_FindCellByHeader(TLISTCTRL lctl, theader_t* header, INT idx)
{
tlistcell_t* cell = 0;
INT i;
if (idx < 0 || idx >= lctl->nitems)
{
return 0;
}
if (header)
{
cell = header->firstcell;
for (i = 0; i == idx && i < lctl->nitems; ++i)
{
cell = cell->next;
}
}
return cell;
}
LONG _TLCTL_GetCellRect(TLISTCTRL lctl, INT col, INT idx, RECT* rect)
{
/*
tlistcell_t* cell = 0;
TLISTCTRL lctl = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
cell = TLCTL_FindCellByIndex(wnd, row, col);
*/
return TUI_OK;
}
LONG TLCTL_OnCreate(TWND wnd)
{
TLISTCTRL lctl = (TLISTCTRL)malloc(sizeof(_TLISTCTRL));
if (!lctl)
{
return TUI_MEM;
}
memset(lctl, 0, sizeof(_TLISTCTRL));
lctl->hdrids = 1;
lctl->editbox = TuiCreateWnd(EDIT,
"",
TWS_CHILD|TES_AUTOHSCROLL,
0, /* y */
0, /* x */
1, /* lines */
1, /* cols */
wnd, /* parent */
lctl->hdrids, /* id */
0); /* no parameter */
if (!lctl->editbox)
{
free(lctl);
return TUI_MEM;
}
lctl->curselrow = -1;
lctl->curselcol = -1;
lctl->firstvisibleitem = -1;
/* increment child ids */
++lctl->hdrids;
/* save memory */
TuiSetWndParam(wnd, (LPVOID)lctl);
return TUI_CONTINUE;
}
VOID TLCTL_OnDestroy(TWND wnd)
{
TLISTCTRL lctl = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
TLC_DeleteAllColumns(wnd);
free(lctl);
}
LONG TLCTL_OnAddColumn(TWND wnd, HEADERITEM* hdritem)
{
TLISTCTRL lctl = 0;
theader_t* header = 0;
RECT rc;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
if (lctl->nitems > 0)
{
/* not allowed to add header after there are any items */
return TUI_ERROR;
}
header = (theader_t*)malloc(sizeof(theader_t));
if (!header)
{
return TUI_MEM;
}
memset(header, 0, sizeof(theader_t));
TuiGetWndRect(TuiGetParent(wnd), &rc);
/*header->caption = hdritem->caption;*/
strncpy(header->caption,
hdritem->caption,
MIN(TUI_MAX_WNDTEXT, strlen(hdritem->caption)));
header->cols = hdritem->cols;
header->align = hdritem->align;
header->attrs = hdritem->attrs;
header->id = lctl->hdrids;
/* make link */
if (lctl->firsthdr)
{
header->prev = lctl->lasthdr;
lctl->lasthdr->next = header;
lctl->lasthdr = header;
}
else
{
lctl->firsthdr = lctl->lasthdr = header;
lctl->firstvisiblehdr = header;
}
/* increment child ids */
++lctl->hdrids;
++lctl->nheaders;
lctl->hdrallwidths += header->cols;
return 0;
}
VOID TLCTL_OnDeleteColumn(TWND wnd, INT col)
{
TLISTCTRL lctl = 0;
theader_t* next = 0;
tlistcell_t* cell = 0;
tlistcell_t* nextcell = 0;
theader_t* header = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
header = _TLCTL_FindHeaderByIndex(lctl, col);
if (!header)
{
return;
}
/* re-link */
next = header->next;
if (next)
{
next->prev = header->prev;
}
if (header->prev)
{
header->prev->next = next;
}
if (header == lctl->firsthdr)
{
lctl->firsthdr = next;
}
else if (header == lctl->lasthdr)
{
lctl->lasthdr = header->prev;
}
/* delete */
header->next = header->prev = 0;
cell = header->firstcell;
while (cell)
{
nextcell = cell->next;
/*free(cell->caption);*/
cell->next = cell->prev = 0;
free(cell);
cell = nextcell;
}
free(header);
/* done */
--lctl->nheaders;
}
VOID TLCTL_OnDeleteAllItems(TWND wnd)
{
INT nitems = 0;
INT i = 0;
TLISTCTRL lctl = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
nitems = lctl->nheaders;
for (i = 0; i < nitems; ++i)
{
TuiSendMsg(wnd, TLCM_DELETEITEM, 0, 0);
}
}
VOID TLC_OnDeleteItem(TWND wnd, INT idx)
{
TLISTCTRL lctl = 0;
tlistcell_t* cell = 0;
tlistcell_t* nextcell = 0;
theader_t* header = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
if (lctl->nitems <= 0 || idx < 0 || idx >= lctl->nitems)
{
return;
}
header = lctl->firsthdr;
while (header)
{
cell = _TLCTL_FindCellByHeader(lctl, header, idx);
nextcell = cell->next;
if (nextcell)
{
nextcell->prev = cell->prev;
}
if (cell->prev)
{
cell->prev->next = nextcell;
}
if (header->firstcell == cell)
{
header->firstcell = cell->next;
}
else if (header->lastcell == cell)
{
header->lastcell = cell->prev;
}
cell->next = cell->prev = 0;
/*free(cell->caption);*/
free(cell);
/* next header */
header = header->next;
}
--lctl->nitems;
}
LONG TLCTL_OnAddItem(TWND wnd, LPSTR text, INT nitems)
{
TLISTCTRL lctl = 0;
INT i = 0;
CHAR* tok;
theader_t* header = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
tlistcell_t* newcell = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
if (lctl->nheaders > 0)
{
/* insert into all listboxes */
header = lctl->firsthdr;
strcpy(buf, text);
tok = strtok(buf, "\t");
while (tok && i < nitems && i < lctl->nheaders)
{
newcell = (tlistcell_t*)malloc(sizeof(tlistcell_t));
if (!newcell)
{
break;
}
memset(newcell, 0, sizeof(tlistcell_t));
/*newcell->caption = (CHAR*)malloc(TUI_MAX_WNDTEXT+1);*/
strncpy(newcell->caption, tok, MIN(TUI_MAX_WNDTEXT, strlen(tok)));
/* add the new item */
if (header->firstcell)
{
newcell->prev = header->lastcell;
header->lastcell->next = newcell;
header->lastcell = newcell;
}
else
{
header->firstcell = header->lastcell = newcell;
lctl->firstvisibleitem = 0;
}
/* insert next */
header = header->next;
tok = strtok(0, "\t");
++i;
}
/* all items count */
++lctl->nitems;
} /* have header */
return lctl->nitems;
}
VOID TLCTL_OnPaint(TWND wnd, TDC dc)
{
TLISTCTRL lctl = 0;
theader_t* header = 0;
INT width = 0;
RECT rcitem, rc, rccell;
CHAR buf[TUI_MAX_WNDTEXT+1];
DWORD attrs = 0;
LONG len = 0;
tlistcell_t* visiblecell = 0;
INT i = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
if (lctl->nheaders <= 0 || !TuiIsWndVisible(wnd))
{
return;
}
/* draw headers */
TuiGetWndRect(wnd, &rc);
rcitem = rc; /* copy some values */
header = lctl->firstvisiblehdr;
width = header->cols;
if (width > rc.cols)
{
width = rc.cols;
}
while (header && width < rc.cols)
{
rcitem.cols = header->cols;
rcitem.x = rc.x + width - rcitem.cols;
attrs = header->attrs;
#ifdef __USE_CURSES__
attrs |= A_REVERSE;
#elif defined __USE_QIO__
attrs = 0;
#endif
len = TuiPrintTextAlignment(buf,
header->caption,
rcitem.cols,
ALIGN_CENTER);
buf[0] = '[';
buf[len-1] = ']';
TuiDrawText(dc,
rcitem.y,
rcitem.x,
buf,
attrs);
/* draw cells */
rccell = rcitem;
rccell.y += 1;
visiblecell = header->firstcell;
for (i = 0; i < lctl->nitems && visiblecell; ++i, visiblecell = visiblecell->next)
{
if (i < lctl->firstvisibleitem)
{
/* do nothing */
continue;
}
else if (i - lctl->firstvisibleitem <= rc.lines - 2)
{
len = TuiPrintTextAlignment(buf,
visiblecell->caption,
header->cols,
header->align);
attrs = visiblecell->attrs;
#ifdef __USE_CURSES__
if (i == lctl->curselrow)
{
attrs |= A_REVERSE;
}
#elif defined __USE_QIO__
#endif
TuiDrawText(dc,
rccell.y,
rccell.x,
buf,
attrs);
++rccell.y;
}
} /* for each drawing cell */
/* draw next header */
header = header->next;
if (header)
{
width += header->cols;
if (width > rc.cols)
{
break;
}
}
} /* while header */
/* print arrow controls */
#ifdef __USE_CURSES__
attrs |= A_REVERSE;
#elif defined __USE_QIO__
attrs = 0;
#endif
if (lctl->firsthdr != lctl->firstvisiblehdr)
{
TuiPutChar(dc, rc.y, rc.x, '<', attrs);
}
/* save the last visible */
if (header)
{
lctl->lastvisiblehdr = header->prev;
TuiPutChar(dc, rc.y, rc.x + width - header->cols - 1, '>', attrs);
}
else
{
lctl->lastvisiblehdr = lctl->lasthdr;
}
TuiMoveYX(dc, rcitem.y,
rcitem.x);
}
VOID TLCTL_OnKeyDown(TWND wnd, LONG ch)
{
TLISTCTRL lctl = 0;
INT repaint = 1;
RECT rc;
INT lines = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
TuiGetWndRect(wnd, &rc);
if (lctl->nheaders <= 0)
{
return;
}
switch (ch)
{
case TVK_SPACE:
{
/*repaint = 1;*/
break;
}
case KEY_RIGHT:
{
if (lctl->lastvisiblehdr != lctl->lasthdr)
{
lctl->firstvisiblehdr = lctl->firstvisiblehdr->next;
++repaint;
}
break;
}
case KEY_LEFT:
{
if (lctl->firstvisiblehdr != lctl->firsthdr)
{
lctl->firstvisiblehdr = lctl->firstvisiblehdr->prev;
++repaint;
}
break;
}
case KEY_DOWN:
{
++lines;
++repaint;
break;
}
case KEY_UP:
{
--lines;
++repaint;
break;
}
case TVK_PRIOR:
#ifdef __USE_CURSES__
case KEY_PPAGE:
#elif (defined __USE_QIO__ && defined __VMS__)
case KEY_PREV:
#endif
{
lines -= rc.lines - 1;
++repaint;
break;
}
case TVK_NEXT:
#ifdef __USE_CURSES__
case KEY_NPAGE:
#elif (defined __USE_QIO__ && defined __VMS__)
case KEY_NEXT:
#endif
{
lines += rc.lines - 1;
++repaint;
break;
}
}
if (repaint)
{
lctl->curselrow += lines;
if (lctl->curselrow >= lctl->nitems)
{
lctl->curselrow = lctl->nitems - 1;
}
else if (lctl->curselrow < 0)
{
lctl->curselrow = 0;
}
if (lctl->curselrow >= lctl->firstvisibleitem + rc.lines - 1)
{
lctl->firstvisibleitem += lines;
if (lctl->firstvisibleitem - 1 > lctl->nitems - rc.lines)
{
lctl->firstvisibleitem = lctl->nitems - rc.lines;
}
}
else if (lctl->firstvisibleitem > lctl->curselrow)
{
lctl->firstvisibleitem += lines;
if (lctl->firstvisibleitem < 0)
{
lctl->firstvisibleitem = 0;
}
}
TuiInvalidateWnd(wnd);
/* send notification */
/*
nmhdr.id = TuiGetWndID(wnd);
nmhdr.ctl = wnd;
nmhdr.code = TLBN_SELCHANGED;
TuiPostMsg(TuiGetParent(wnd), TWM_NOTIFY, 0, (LPARAM)&nmhdr);
*/
}
}
LONG TLCM_OnGetItemCount(TWND wnd)
{
TLISTCTRL lctl = 0;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
return lctl->nitems;
}
LONG TLCTL_OnSetItem(TWND wnd, UINT flags, SUBITEM* subitem)
{
TLISTCTRL lctl = 0;
tlistcell_t* cell = 0;
LONG rc = TUI_ERROR;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
cell = _TLCTL_FindCellByIndex(lctl, subitem->col, subitem->idx);
if (cell)
{
if (flags & LCFM_TEXT) { strcpy(cell->caption, subitem->text); }
if (flags & LCFM_DATA) { cell->data = subitem->data; }
if (flags & LCFM_ATTRS) { cell->attrs = subitem->attrs; }
rc = TUI_OK;
}
return rc;
}
LONG TLCTL_OnGetItem(TWND wnd, UINT flags, SUBITEM* subitem)
{
TLISTCTRL lctl = 0;
tlistcell_t* cell = 0;
LONG rc = TUI_ERROR;
lctl = (TLISTCTRL)TuiGetWndParam(wnd);
cell = _TLCTL_FindCellByIndex(lctl, subitem->col, subitem->idx);
if (cell)
{
if (flags & LCFM_TEXT) { subitem->text = cell->caption; }
if (flags & LCFM_DATA) { subitem->data = cell->data; }
if (flags & LCFM_ATTRS) { subitem->attrs = cell->attrs; }
rc = TUI_OK;
}
return rc;
}
LONG LISTCTRLPROC(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_CREATE:
{
/* initial memory for static control */
return TLCTL_OnCreate(wnd);
}
case TWM_DESTROY:
{
/* release memory of static control */
TLCTL_OnDestroy(wnd);
return 0;
}
/*
case TWM_SETFOCUS:
{
TLCTL_OnSetFocus(wnd);
break;
}
case TWM_KILLFOCUS:
{
return TLCTL_OnKillFocus(wnd);
}
*/
case TWM_KEYDOWN:
{
TLCTL_OnKeyDown(wnd, (LONG)wparam);
break;
}
case TWM_PAINT:
{
TLCTL_OnPaint(wnd, TuiGetDC(wnd));
return 0;
}
case TLCM_ADDCOLUMN:
{
return TLCTL_OnAddColumn(wnd, (HEADERITEM*)lparam);
}
case TLCM_DELETECOLUMN:
{
TLCTL_OnDeleteColumn(wnd, (INT)wparam);
return 0;
}
case TLCM_DELETEALLCOLUMNS:
{
TLCTL_OnDeleteAllItems(wnd);
return 0;
}
case TLCM_ADDITEM:
{
return TLCTL_OnAddItem(wnd, (LPSTR)lparam, (INT)wparam);
}
case TLCM_DELETEITEM:
{
TLC_OnDeleteItem(wnd, (INT)wparam);
return 0;
}
case TLCM_DELETEALLITEMS:
{
TLCTL_OnDeleteAllItems(wnd);
return 0;
}
case TLCM_SETITEM:
{
return TLCTL_OnSetItem(wnd, (UINT)wparam, (SUBITEM*)lparam);
}
case TLCM_GETITEM:
{
return TLCTL_OnGetItem(wnd, (UINT)wparam, (SUBITEM*)lparam);
}
case TLCM_GETITEMCOUNT:
{
return TLCM_OnGetItemCount(wnd);
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
/*-------------------------------------------------------------------
* File name: tui_test.c
* Author: Seree Rakwong
* Date: 17-SEP-18
*-----------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curses.h>
#include "tui.h"
#define IDC_STATUSBAR 199
#define IDC_NAME 200
#define IDC_LISTBOX1 204
#define IDC_PASSWORD 205
#define IDC_OK 206
#define IDC_CANCEL 207
#define IDC_LISTBOX2 208
#define IDC_LISTBOX3 209
#define IDC_CLOSE 210
#define IDC_SAVE 211
#define IDC_OPENDLG2 212
#define IDC_OPENDLG3 213
#define IDC_MSG 214
#define IDC_PRICE 215
WNDTEMPL dlg1[] =
{
/* 1st object is always dialog */
{ "mywndproc", "Dialog1", 1, 0, 0, 25, 80, TWS_WINDOW, 0 },
/* 2nd and others are controls */
{ STATIC, "Name:", 100, 1, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "12345678901234567890", IDC_NAME, 1, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|
TES_LEFT|TES_APPENDMODE|TES_UPPERCASE|TES_AUTOHSCROLL, 0 },
{ STATIC, "ID:", 101, 2, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "DT66234", 201, 2, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|
TES_CENTER|TES_AUTOHSCROLL, 0 },
{ STATIC, "Tel:", 102, 3, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "1234", 202, 3, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|
TES_NUMBER|TES_RIGHT|TES_AUTOHSCROLL, 0 },
{ STATIC, "Email:", 103, 4, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "abc@abc.com", 203, 4, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|TWS_DISABLED|
TES_AUTOHSCROLL, 0 },
{ STATIC, "Password:", 104, 5, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "welcome1!", IDC_PASSWORD, 5, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|
TES_LEFT|TES_PASSWORD|TES_AUTOHSCROLL, 0 },
{ STATIC, "Price:", 105, 6, 1, 1, 16, TWS_CHILD|TWS_VISIBLE|TSS_RIGHT, 0 },
{ EDIT, "399.50", IDC_PRICE, 6, 18, 1, 16,
TWS_CHILD|TWS_VISIBLE|
TES_RIGHT|TES_DECIMAL|TES_AUTOHSCROLL, 0 },
{ LISTBOX,"", IDC_LISTBOX1, 8, 1, 5, 16, TWS_CHILD|TWS_VISIBLE|TLBS_CENTER, 0 },
{ LISTBOX,"", IDC_LISTBOX2, 8, 21, 5, 16,
TWS_CHILD|TWS_VISIBLE|TLBS_CHECKBOX, 0 },
{ LISTBOX,"", IDC_LISTBOX3, 8, 41, 5, 16,
TWS_CHILD|TWS_VISIBLE|TLBS_RADIOBOX|TLBS_RIGHT, 0 },
{ BUTTON, "Dlg2", IDC_OPENDLG2, 14, 1, 1, 10, TWS_CHILD|TWS_VISIBLE|TWS_DISABLED, 0 },
{ BUTTON, "Dlg3", IDC_OPENDLG3, 14, 21, 1, 10, TWS_CHILD|TWS_VISIBLE, 0 },
{ BUTTON, "Close", IDC_CLOSE, 14, 41, 1, 11, TWS_CHILD|TWS_VISIBLE, 0 },
{ STATIC, "Esc to exit: ", IDC_STATUSBAR, 24, 0, 1, 80, TWS_CHILD|TWS_VISIBLE|TWS_DISABLED|TSS_LEFT, 0 },
/* the last is the end-of-controls */
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
WNDTEMPL dlg3[] =
{
/* 1st object is always dialog */
{ "mylistctlproc", "Dialog3", 2, 0, 0, 25, 80, TWS_WINDOW, 0 },
/* 2nd and others are controls */
{ LISTCTRL, "", IDC_OK, 1, 1, 16, 79, TWS_CHILD|TWS_VISIBLE, 0 },
{ BUTTON, "Message", IDC_MSG, 20, 20, 1, 15, TWS_CHILD|TWS_VISIBLE, 0 },
{ BUTTON, "Close", IDC_CLOSE, 20, 40, 1, 11, TWS_CHILD|TWS_VISIBLE, 0 },
/* the last is the end-of-controls */
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
WNDTEMPL msgbox[] =
{
/* 1st object is always dialog */
{ "msgbox", "msgbox", 3, 10, 10, 7, 40, TWS_WINDOW, 0 },
/* 2nd and others are controls */
{ STATIC, "This is a message box", IDC_MSG, 1, 1, 1, 38,
TWS_CHILD|TWS_VISIBLE|TSS_CENTER, 0 },
{ BUTTON, "OK", IDC_OK, 3, 5, 1, 10, TWS_CHILD|TWS_VISIBLE, 0 },
{ BUTTON, "Cancel", IDC_CANCEL, 3, 20, 1, 10, TWS_CHILD|TWS_VISIBLE, 0 },
/* the last is the end-of-controls */
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
VOID mywndproc_onselchanged(TWND wnd, TWND ctl)
{
TWND statusbar = 0;
TWND listbox = 0;
INT i = 0;
CHAR buf[TUI_MAX_WNDTEXT+1];
statusbar = TuiGetWndItem(wnd, IDC_STATUSBAR);
listbox = ctl;
i = TLB_GetCurSel(listbox);
if (i >= 0)
{
TLB_GetItemText(listbox, i, buf);
TuiSetWndText(statusbar, buf);
}
}
LONG mywndproc(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
CHAR buf[TUI_MAX_WNDTEXT+1];
INT i;
TWND statusbar = 0;
TWND listbox = 0;
TWND edit = 0;
NMHDR* nmhdr = 0;
switch (msg)
{
case TWM_INITDIALOG:
{
listbox = TuiGetWndItem(wnd, IDC_LISTBOX1);
for (i = 0; i < 20; ++i)
{
sprintf(buf, "Item %d", (i));
TLB_AddItem(listbox, buf);
}
TLB_DeleteItem(listbox, 5);
TLB_SetCurSel(listbox, 7);
listbox = TuiGetWndItem(wnd, IDC_LISTBOX2);
for (i = 0; i < 10; ++i)
{
sprintf(buf, "Item %d", (i));
TLB_AddItem(listbox, buf);
}
listbox = TuiGetWndItem(wnd, IDC_LISTBOX3);
for (i = 0; i < 10; ++i)
{
sprintf(buf, "Item %d", (i));
TLB_AddItem(listbox, buf);
}
edit = TuiGetWndItem(wnd, IDC_NAME);
TuiSendMsg(edit, TEM_LIMITTEXT, (WPARAM)20, (LPARAM)0);
statusbar = TuiGetWndItem(wnd, IDC_STATUSBAR);
#ifdef __USE_CURSES__
TuiSendMsg(statusbar, TWM_SETTEXTATTRS, (WPARAM)(A_REVERSE), (LPARAM)0);
#endif
edit = TuiGetWndItem(wnd, IDC_PRICE);
TuiSendMsg(edit, TEM_SETDECWIDTH, (WPARAM)2, (LPARAM)0);
/*
edit = TuiGetWndItem(wnd, IDC_PASSWORD);
TEDT_ShowPasswdChar(edit, TW_HIDE);*/
return TUI_CONTINUE;
}
case TWM_NOTIFY:
{
nmhdr = (NMHDR*)lparam;
switch (nmhdr->code)
{
case TLBN_SELCHANGED:
{
mywndproc_onselchanged(wnd, nmhdr->ctl);
break;
}
}
break;
}
case TWM_COMMAND:
{
sprintf(buf, "Pressed: %s", (IDC_OK == wparam ? "OK" : "Cancel"));
statusbar = TuiGetWndItem(wnd, IDC_STATUSBAR);
TuiSetWndText(statusbar, buf);
if (wparam == IDC_OPENDLG2)
{
}
else if (wparam == IDC_OPENDLG3)
{
TWND dlg = TuiCreateWndTempl(dlg3, 0);
TuiShowWnd(dlg, 1);
}
else if (wparam == IDC_CLOSE)
{
TuiPostQuitMsg(0);
}
break;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
LONG mylistctlproc(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
TWND list = 0;
switch (msg)
{
case TWM_INITDIALOG:
{
list = TuiGetWndItem(wnd, IDC_OK);
#ifdef __USE_CURSES__
TLC_AddColumn(list, "STOCK", 20, ALIGN_LEFT, COLOR_PAIR(BLUE_YELLOW));
TLC_AddColumn(list, "DATE", 16, ALIGN_CENTER, COLOR_PAIR(BLUE_YELLOW));
TLC_AddColumn(list, "OPEN", 16, ALIGN_RIGHT, COLOR_PAIR(BLUE_YELLOW));
TLC_AddColumn(list, "HIGH", 16, ALIGN_RIGHT, COLOR_PAIR(BLUE_YELLOW));
TLC_AddColumn(list, "LOW", 16, ALIGN_RIGHT, COLOR_PAIR(BLUE_YELLOW));
TLC_AddColumn(list, "CLOSE", 16, ALIGN_RIGHT, COLOR_PAIR(BLUE_YELLOW));
#else
TLC_AddColumn(list, "STOCK", 20, ALIGN_LEFT, BLUE_YELLOW);
TLC_AddColumn(list, "DATE", 16, ALIGN_CENTER, BLUE_YELLOW);
TLC_AddColumn(list, "OPEN", 16, ALIGN_RIGHT, BLUE_YELLOW);
TLC_AddColumn(list, "HIGH", 16, ALIGN_RIGHT, BLUE_YELLOW);
TLC_AddColumn(list, "LOW", 16, ALIGN_RIGHT, BLUE_YELLOW);
TLC_AddColumn(list, "CLOSE", 16, ALIGN_RIGHT, BLUE_YELLOW);
#endif
TLC_AddItem(list, "PTT\t01-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t02-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t03-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t04-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t05-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t06-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t07-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t08-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t09-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t10-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t11-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t12-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t13-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t14-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t15-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t16-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t17-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t18-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t19-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t20-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t21-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t22-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t23-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t24-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t25-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t26-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t27-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t28-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t29-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
TLC_AddItem(list, "PTT\t30-01-2018\t60.00\t63.50\t60.00\t62.00\t", 6);
return TUI_CONTINUE;
}
case TWM_COMMAND:
{
if (wparam == IDC_CLOSE)
{
TuiDestroyWnd(wnd);
}
else if (wparam == IDC_MSG)
{
UINT rc = TuiMsgBox(wnd,
"Hello world",
"Welcome to the real world.",
MB_YESNOCANCEL);
switch (rc)
{
case MB_YES: TuiMsgBox(wnd, "Hello TUI", "Clicked YES", MB_OK); break;
case MB_NO: TuiMsgBox(wnd, "Hello TUI", "Clicked NO", MB_OK); break;
case MB_CANCEL: TuiMsgBox(wnd, "Hello TUI", "Clicked CANCEL", MB_OK); break;
}
}
break;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
LONG msgboxproc(TWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case TWM_INITDIALOG:
{
#ifdef __USE_CURSES__
TuiSendMsg(wnd, TWM_SETTEXTATTRS, (WPARAM)(A_REVERSE), (LPARAM)0);
#endif
return TUI_CONTINUE;
}
case TWM_COMMAND:
{
if (wparam == IDC_CANCEL)
{
TuiDestroyWnd(wnd);
}
break;
}
}
return TuiDefWndProc(wnd, msg, wparam, lparam);
}
int main(int argc, char* argv[])
{
MSG msg;
TWND wnd;
TuiStartup();
TuiSetNextMove(TVK_TAB);
TuiRegisterCls("mywndproc", mywndproc);
TuiRegisterCls("mylistctlproc", mylistctlproc);
TuiRegisterCls("msgbox", msgboxproc);
wnd = TuiCreateWndTempl(dlg1, 0);
if (!wnd)
{
TuiShutdown();
return -1;
}
TuiShowWnd(wnd, 1);
while (TuiGetMsg(&msg))
{
TuiDispatchMsg(&msg);
TuiTranslateMsg(&msg);
}
TuiShutdown();
return 0;
}