📄 listbox.c
字号:
/*
** $Id: listbox.c,v 1.56 2004/07/17 12:54:24 weiym Exp $
**
** listbox.c: the List Box Control module.
**
** Copyright (C) 2003 Feynman Software.
** Copyright (C) 1999 ~ 2002 Wei Yongming.
**
** Current maintainer: Wei Yongming.
**
** Note:
** Although there was a version by Zhao Jianghua, this version of
** LISTBOX control is written by Wei Yongming from scratch.
**
** Create date: 1999/8/31
**
*/
/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
** TODO:
** * Multiple columns support.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "window.h"
#include "control.h"
#include "cliprect.h"
#include "internals.h"
#include "ctrlclass.h"
#ifdef _CTRL_LISTBOX
#include "ctrlmisc.h"
#include "listbox.h"
#define _USE_FIXSTR 1
#define ITEM_BOTTOM(x) (x->itemTop + x->itemVisibles - 1)
#define LST_WIDTH_CHECKMARK 11
#define LST_HEIGHT_CHECKMARK 11
#define LST_INTER_BMPTEXT 2
static const BITMAP* bmp_checkmark;
#define CHECKMARK_BMP bmp_checkmark
static int ListboxCtrlProc (HWND hwnd, int message, WPARAM wParam, LPARAM lParam);
BOOL RegisterListboxControl (void)
{
WNDCLASS WndClass;
if ((bmp_checkmark = GetStockBitmap (STOCKBMP_CHECKMARK, -1, -1)) == NULL)
return FALSE;
WndClass.spClassName = CTRL_LISTBOX;
WndClass.dwStyle = WS_NONE;
WndClass.dwExStyle = WS_EX_NONE;
WndClass.hCursor = GetSystemCursor (0);
WndClass.iBkColor = GetWindowElementColor (BKC_EDIT_DEF);
WndClass.WinProc = ListboxCtrlProc;
return AddNewControlClass (&WndClass) == ERR_OK;
}
#if 0
void ListboxControlCleanup (void)
{
return;
}
#endif
static BOOL lstInitListBoxData (HWND hwnd, PCONTROL pCtrl, LISTBOXDATA* pData, int len)
{
int i;
PLISTBOXITEM plbi;
pData->itemHeight = pCtrl->pLogFont->size;
pData->itemHilighted = 0;
pData->str_cmp = strncmp;
// init item buffer.
if (!(pData->buffStart = malloc (len * sizeof (LISTBOXITEM))))
return FALSE;
pData->buffLen = len;
pData->buffEnd = pData->buffStart + len;
pData->freeList = pData->buffStart;
plbi = pData->freeList;
for (i = 0; i < len - 1; i++) {
plbi->next = plbi + 1;
plbi ++;
}
plbi->next = NULL;
if (GetWindowStyle (hwnd) & LBS_SBALWAYS)
pData->sbPolicy = SB_POLICY_ALWAYS;
else
pData->sbPolicy = SB_POLICY_AUTOMATIC;
return TRUE;
}
static void lstListBoxCleanUp (LISTBOXDATA* pData)
{
PLISTBOXITEM plbi;
PLISTBOXITEM next;
plbi = pData->head;
while (plbi) {
#if _USE_FIXSTR
FreeFixStr (plbi->key);
#else
free (plbi->key);
#endif
next = plbi->next;
if (plbi < pData->buffStart || plbi > pData->buffEnd)
free (plbi);
plbi = next;
}
free (pData->buffStart);
}
static void lstResetListBoxContent (PLISTBOXDATA pData)
{
int i;
PLISTBOXITEM plbi, next;
pData->itemCount = 0;
pData->itemTop = 0;
pData->itemHilighted = 0;
plbi = pData->head;
while (plbi) {
#if _USE_FIXSTR
FreeFixStr (plbi->key);
#else
free (plbi->key);
#endif
next = plbi->next;
if (plbi < pData->buffStart || plbi > pData->buffEnd)
free (plbi);
plbi = next;
}
pData->head = NULL;
pData->freeList = pData->buffStart;
plbi = pData->freeList;
for (i = 0; i < pData->buffLen - 1; i++) {
plbi->next = plbi + 1;
plbi ++;
}
plbi->next = NULL;
return;
}
static PLISTBOXITEM lstAllocItem (PLISTBOXDATA pData)
{
PLISTBOXITEM plbi;
if (pData->freeList) {
plbi = pData->freeList;
pData->freeList = plbi->next;
}
else
plbi = (PLISTBOXITEM) malloc (sizeof (LISTBOXITEM));
return plbi;
}
static void lstFreeItem (PLISTBOXDATA pData, PLISTBOXITEM plbi)
{
if (plbi < pData->buffStart || plbi > pData->buffEnd)
free (plbi);
else {
plbi->next = pData->freeList;
pData->freeList = plbi;
}
}
static int lstAddNewItem (DWORD dwStyle,
PLISTBOXDATA pData, PLISTBOXITEM newItem, int pos)
{
PLISTBOXITEM plbi;
PLISTBOXITEM insPosItem = NULL;
int insPos = 0;
newItem->next = NULL;
if (!pData->head)
insPosItem = NULL;
else if (dwStyle & LBS_SORT) {
plbi = pData->head;
if (pData->str_cmp (newItem->key, plbi->key, (size_t)-1) < 0) {
insPosItem = NULL;
insPos = 0;
}
else {
while (plbi->next) {
if (pData->str_cmp (newItem->key, plbi->next->key, (size_t)-1) <= 0)
break;
plbi = plbi->next;
insPos ++;
}
insPosItem = plbi;
}
}
else {
plbi = pData->head;
if (pos < 0) {
while (plbi->next) {
plbi = plbi->next;
insPos ++;
}
insPosItem = plbi;
}
else if (pos == 0) {
insPosItem = NULL;
insPos = 0;
}
else {
int index = 1;
while (plbi) {
if (pos == index)
break;
plbi = plbi->next;
index ++;
insPos ++;
}
insPosItem = plbi;
}
}
if (insPosItem) {
plbi = insPosItem->next;
insPosItem->next = newItem;
newItem->next = plbi;
insPos ++;
}
else {
plbi = pData->head;
pData->head = newItem;
newItem->next = plbi;
}
pData->itemCount ++;
return insPos;
}
static PLISTBOXITEM lstRemoveItem (PLISTBOXDATA pData, int* pos)
{
int index = 0;
PLISTBOXITEM plbi, prev;
if (!pData->head)
return NULL;
if (*pos < 0) {
prev = pData->head;
plbi = pData->head;
while (plbi->next) {
prev = plbi;
plbi = plbi->next;
index ++;
}
if (plbi == pData->head) {
pData->head = pData->head->next;
*pos = 0;
return plbi;
}
else {
prev->next = plbi->next;
*pos = index;
return plbi;
}
}
else if (*pos == 0) {
plbi = pData->head;
pData->head = plbi->next;
return plbi;
}
else {
index = 0;
prev = pData->head;
plbi = pData->head;
while (plbi->next) {
if (*pos == index)
break;
prev = plbi;
plbi = plbi->next;
index ++;
}
if (plbi == pData->head) {
pData->head = pData->head->next;
*pos = 0;
return plbi;
}
else {
prev->next = plbi->next;
*pos = index;
return plbi;
}
}
return NULL;
}
static void lstGetItemsRect (PLISTBOXDATA pData,
int start, int end, RECT* prc)
{
if (start < 0)
start = 0;
prc->top = (start - pData->itemTop)*pData->itemHeight;
if (end >= 0)
prc->bottom = (end - pData->itemTop + 1)*pData->itemHeight;
}
static void lstInvalidateItem (HWND hwnd, PLISTBOXDATA pData, int pos)
{
RECT rcInv;
if (pos < pData->itemTop || pos > (pData->itemTop + pData->itemVisibles))
return;
GetClientRect (hwnd, &rcInv);
rcInv.top = (pos - pData->itemTop)*pData->itemHeight;
rcInv.bottom = rcInv.top + pData->itemHeight;
InvalidateRect (hwnd, &rcInv, TRUE);
}
static BOOL lstInvalidateUnderItem (HWND hwnd, PLISTBOXDATA pData, int pos)
{
RECT rcInv;
if (pos > (pData->itemTop + pData->itemVisibles))
return FALSE;
if (pos <= pData->itemTop) {
InvalidateRect (hwnd, NULL, TRUE);
return TRUE;
}
GetClientRect (hwnd, &rcInv);
lstGetItemsRect (pData, pos, -1, &rcInv);
if (rcInv.top < rcInv.bottom)
InvalidateRect (hwnd, &rcInv, TRUE);
return TRUE;
}
static PLISTBOXITEM lstGetItem (PLISTBOXDATA pData, int pos)
{
int i;
PLISTBOXITEM plbi;
plbi = pData->head;
for (i=0; i < pos && plbi; i++)
plbi = plbi->next;
return plbi;
}
static int lstFindItem (PLISTBOXDATA pData, int start, char* key, BOOL bExact)
{
PLISTBOXITEM plbi;
int keylen = strlen (key);
if (start >= pData->itemCount)
start = 0;
else if (start < 0)
start = 0;
plbi = lstGetItem (pData, start);
while (plbi)
{
if (bExact && (keylen != strlen (plbi->key))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -