reactos/rosapps/dflat32/listbox.c
KJK::Hyperion c37620bed9 Cosmetics...
svn path=/trunk/; revision=4923
2003-06-19 03:17:56 +00:00

470 lines
14 KiB
C

/* ------------- listbox.c ------------ */
#include "dflat.h"
#ifdef INCLUDE_EXTENDEDSELECTIONS
static int ExtendSelections(DFWINDOW, int, int);
static void TestExtended(DFWINDOW, DF_PARAM);
static void ClearAllSelections(DFWINDOW);
static void SetSelection(DFWINDOW, int);
static void FlipSelection(DFWINDOW, int);
static void ClearSelection(DFWINDOW, int);
#else
#define TestExtended(w,p) /**/
#endif
static void ChangeSelection(DFWINDOW, int, int);
static void WriteSelection(DFWINDOW, int, int, DFRECT *);
static BOOL SelectionInWindow(DFWINDOW, int);
static int py = -1; /* the previous y mouse coordinate */
#ifdef INCLUDE_EXTENDEDSELECTIONS
/* --------- DF_SHIFT_F8 Key ------------ */
static void AddModeKey(DFWINDOW wnd)
{
if (DfIsMultiLine(wnd)) {
wnd->AddMode ^= TRUE;
DfSendMessage(DfGetParent(wnd), DFM_ADDSTATUS,
wnd->AddMode ? ((DF_PARAM) "Add Mode") : 0, 0);
}
}
#endif
/* --------- DF_UP (Up Arrow) Key ------------ */
static void UpKey(DFWINDOW wnd, DF_PARAM p2)
{
if (wnd->selection > 0) {
if (wnd->selection == wnd->wtop) {
DfBaseWndProc(DF_LISTBOX, wnd, DFM_KEYBOARD, DF_UP, p2);
DfPostMessage(wnd, DFM_LB_SELECTION, wnd->selection-1,
DfIsMultiLine(wnd) ? p2 : FALSE);
}
else {
int newsel = wnd->selection-1;
if (wnd->wlines == DfClientHeight(wnd))
while (*DfTextLine(wnd, newsel) == DF_LINE)
--newsel;
DfPostMessage(wnd, DFM_LB_SELECTION, newsel,
#ifdef INCLUDE_EXTENDEDSELECTIONS
DfIsMultiLine(wnd) ? p2 :
#endif
FALSE);
}
}
}
/* --------- DF_DN (Down Arrow) Key ------------ */
static void DnKey(DFWINDOW wnd, DF_PARAM p2)
{
if (wnd->selection < wnd->wlines-1) {
if (wnd->selection == wnd->wtop+DfClientHeight(wnd)-1) {
DfBaseWndProc(DF_LISTBOX, wnd, DFM_KEYBOARD, DF_DN, p2);
DfPostMessage(wnd, DFM_LB_SELECTION, wnd->selection+1,
DfIsMultiLine(wnd) ? p2 : FALSE);
}
else {
int newsel = wnd->selection+1;
if (wnd->wlines == DfClientHeight(wnd))
while (*DfTextLine(wnd, newsel) == DF_LINE)
newsel++;
DfPostMessage(wnd, DFM_LB_SELECTION, newsel,
#ifdef INCLUDE_EXTENDEDSELECTIONS
DfIsMultiLine(wnd) ? p2 :
#endif
FALSE);
}
}
}
/* --------- DF_HOME and DF_PGUP Keys ------------ */
static void HomePgUpKey(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
DfBaseWndProc(DF_LISTBOX, wnd, DFM_KEYBOARD, p1, p2);
DfPostMessage(wnd, DFM_LB_SELECTION, wnd->wtop,
#ifdef INCLUDE_EXTENDEDSELECTIONS
DfIsMultiLine(wnd) ? p2 :
#endif
FALSE);
}
/* --------- DF_END and DF_PGDN Keys ------------ */
static void EndPgDnKey(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
int bot;
DfBaseWndProc(DF_LISTBOX, wnd, DFM_KEYBOARD, p1, p2);
bot = wnd->wtop+DfClientHeight(wnd)-1;
if (bot > wnd->wlines-1)
bot = wnd->wlines-1;
DfPostMessage(wnd, DFM_LB_SELECTION, bot,
#ifdef INCLUDE_EXTENDEDSELECTIONS
DfIsMultiLine(wnd) ? p2 :
#endif
FALSE);
}
#ifdef INCLUDE_EXTENDEDSELECTIONS
/* --------- Space Bar Key ------------ */
static void SpacebarKey(DFWINDOW wnd, DF_PARAM p2)
{
if (DfIsMultiLine(wnd)) {
int sel = DfSendMessage(wnd, DFM_LB_CURRENTSELECTION, 0, 0);
if (sel != -1) {
if (wnd->AddMode)
FlipSelection(wnd, sel);
if (DfItemSelected(wnd, sel)) {
if (!((int) p2 & (DF_LEFTSHIFT | DF_RIGHTSHIFT)))
wnd->AnchorPoint = sel;
ExtendSelections(wnd, sel, (int) p2);
}
else
wnd->AnchorPoint = -1;
DfSendMessage(wnd, DFM_PAINT, 0, 0);
}
}
}
#endif
/* --------- Enter ('\r') Key ------------ */
static void EnterKey(DFWINDOW wnd)
{
if (wnd->selection != -1) {
DfSendMessage(wnd, DFM_LB_SELECTION, wnd->selection, TRUE);
DfSendMessage(wnd, DFM_LB_CHOOSE, wnd->selection, 0);
}
}
/* --------- All Other Key Presses ------------ */
static void KeyPress(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
int sel = wnd->selection+1;
while (sel < wnd->wlines) {
char *cp = DfTextLine(wnd, sel);
if (cp == NULL)
break;
#ifdef INCLUDE_EXTENDEDSELECTIONS
if (DfIsMultiLine(wnd))
cp++;
#endif
/* --- special for directory list box --- */
if (*cp == '[')
cp++;
if (tolower(*cp) == (int)p1) {
DfSendMessage(wnd, DFM_LB_SELECTION, sel,
DfIsMultiLine(wnd) ? p2 : FALSE);
if (!SelectionInWindow(wnd, sel)) {
wnd->wtop = sel-DfClientHeight(wnd)+1;
DfSendMessage(wnd, DFM_PAINT, 0, 0);
}
break;
}
sel++;
}
}
/* --------- DFM_KEYBOARD Message ------------ */
static int KeyboardMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
switch ((int) p1) {
#ifdef INCLUDE_EXTENDEDSELECTIONS
case DF_SHIFT_F8:
AddModeKey(wnd);
return TRUE;
#endif
case DF_UP:
TestExtended(wnd, p2);
UpKey(wnd, p2);
return TRUE;
case DF_DN:
TestExtended(wnd, p2);
DnKey(wnd, p2);
return TRUE;
case DF_PGUP:
case DF_HOME:
TestExtended(wnd, p2);
HomePgUpKey(wnd, p1, p2);
return TRUE;
case DF_PGDN:
case DF_END:
TestExtended(wnd, p2);
EndPgDnKey(wnd, p1, p2);
return TRUE;
#ifdef INCLUDE_EXTENDEDSELECTIONS
case ' ':
SpacebarKey(wnd, p2);
break;
#endif
case '\r':
EnterKey(wnd);
return TRUE;
default:
KeyPress(wnd, p1, p2);
break;
}
return FALSE;
}
/* ------- DFM_LEFT_BUTTON Message -------- */
static int LeftButtonMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
int my = (int) p2 - DfGetTop(wnd);
if (my >= wnd->wlines-wnd->wtop)
my = wnd->wlines - wnd->wtop;
if (!DfInsideRect(p1, p2, DfClientRect(wnd)))
return FALSE;
if (wnd->wlines && my != py) {
int sel = wnd->wtop+my-1;
#ifdef INCLUDE_EXTENDEDSELECTIONS
int sh = DfGetShift();
if (!(sh & (DF_LEFTSHIFT | DF_RIGHTSHIFT))) {
if (!(sh & DF_CTRLKEY))
ClearAllSelections(wnd);
wnd->AnchorPoint = sel;
DfSendMessage(wnd, DFM_PAINT, 0, 0);
}
#endif
DfSendMessage(wnd, DFM_LB_SELECTION, sel, TRUE);
py = my;
}
return TRUE;
}
/* ------------- DOUBLE_CLICK Message ------------ */
static int DoubleClickMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
if (DfWindowMoving || DfWindowSizing)
return FALSE;
if (wnd->wlines) {
DFRECT rc = DfClientRect(wnd);
DfBaseWndProc(DF_LISTBOX, wnd, DOUBLE_CLICK, p1, p2);
if (DfInsideRect(p1, p2, rc))
DfSendMessage(wnd, DFM_LB_CHOOSE, wnd->selection, 0);
}
return TRUE;
}
/* ------------ DFM_ADDTEXT Message -------------- */
static int AddTextMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
int rtn = DfBaseWndProc(DF_LISTBOX, wnd, DFM_ADDTEXT, p1, p2);
if (wnd->selection == -1)
DfSendMessage(wnd, DFM_LB_SETSELECTION, 0, 0);
#ifdef INCLUDE_EXTENDEDSELECTIONS
if (*(char *)p1 == DF_LISTSELECTOR)
wnd->SelectCount++;
#endif
return rtn;
}
/* --------- DFM_GETTEXT Message ------------ */
static void GetTextMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
if ((int)p2 != -1) {
char *cp1 = (char *)p1;
char *cp2 = DfTextLine(wnd, (int)p2);
while (cp2 && *cp2 && *cp2 != '\n')
*cp1++ = *cp2++;
*cp1 = '\0';
}
}
/* --------- DF_LISTBOX Window Processing Module ------------ */
int DfListBoxProc(DFWINDOW wnd, DFMESSAGE msg, DF_PARAM p1, DF_PARAM p2)
{
switch (msg) {
case DFM_CREATE_WINDOW:
DfBaseWndProc(DF_LISTBOX, wnd, msg, p1, p2);
wnd->selection = -1;
#ifdef INCLUDE_EXTENDEDSELECTIONS
wnd->AnchorPoint = -1;
#endif
return TRUE;
case DFM_KEYBOARD:
if (DfWindowMoving || DfWindowSizing)
break;
if (KeyboardMsg(wnd, p1, p2))
return TRUE;
break;
case DFM_LEFT_BUTTON:
if (LeftButtonMsg(wnd, p1, p2) == TRUE)
return TRUE;
break;
case DOUBLE_CLICK:
if (DoubleClickMsg(wnd, p1, p2))
return TRUE;
break;
case DFM_BUTTON_RELEASED:
if (DfWindowMoving || DfWindowSizing || DfVSliding)
break;
py = -1;
return TRUE;
case DFM_ADDTEXT:
return AddTextMsg(wnd, p1, p2);
case DFM_LB_GETTEXT:
GetTextMsg(wnd, p1, p2);
return TRUE;
case DFM_CLEARTEXT:
wnd->selection = -1;
#ifdef INCLUDE_EXTENDEDSELECTIONS
wnd->AnchorPoint = -1;
#endif
wnd->SelectCount = 0;
break;
case DFM_PAINT:
DfBaseWndProc(DF_LISTBOX, wnd, msg, p1, p2);
WriteSelection(wnd, wnd->selection, TRUE, (DFRECT *)p1);
return TRUE;
case DFM_SCROLL:
case DFM_HORIZSCROLL:
case DFM_SCROLLPAGE:
case DFM_HORIZPAGE:
case DFM_SCROLLDOC:
DfBaseWndProc(DF_LISTBOX, wnd, msg, p1, p2);
WriteSelection(wnd,wnd->selection,TRUE,NULL);
return TRUE;
case DFM_LB_CHOOSE:
DfSendMessage(DfGetParent(wnd), DFM_LB_CHOOSE, p1, p2);
return TRUE;
case DFM_LB_SELECTION:
ChangeSelection(wnd, (int) p1, (int) p2);
DfSendMessage(DfGetParent(wnd), DFM_LB_SELECTION,
wnd->selection, 0);
return TRUE;
case DFM_LB_CURRENTSELECTION:
return wnd->selection;
case DFM_LB_SETSELECTION:
ChangeSelection(wnd, (int) p1, 0);
return TRUE;
#ifdef INCLUDE_EXTENDEDSELECTIONS
case DFM_CLOSE_WINDOW:
if (DfIsMultiLine(wnd) && wnd->AddMode) {
wnd->AddMode = FALSE;
DfSendMessage(DfGetParent(wnd), DFM_ADDSTATUS, 0, 0);
}
break;
#endif
default:
break;
}
return DfBaseWndProc(DF_LISTBOX, wnd, msg, p1, p2);
}
static BOOL SelectionInWindow(DFWINDOW wnd, int sel)
{
return (wnd->wlines && sel >= wnd->wtop &&
sel < wnd->wtop+DfClientHeight(wnd));
}
static void WriteSelection(DFWINDOW wnd, int sel,
int reverse, DFRECT *rc)
{
if (DfIsVisible(wnd))
if (SelectionInWindow(wnd, sel))
DfWriteTextLine(wnd, rc, sel, reverse);
}
#ifdef INCLUDE_EXTENDEDSELECTIONS
/* ----- Test for extended selections in the listbox ----- */
static void TestExtended(DFWINDOW wnd, DF_PARAM p2)
{
if (DfIsMultiLine(wnd) && !wnd->AddMode &&
!((int) p2 & (DF_LEFTSHIFT | DF_RIGHTSHIFT))) {
if (wnd->SelectCount > 1) {
ClearAllSelections(wnd);
DfSendMessage(wnd, DFM_PAINT, 0, 0);
}
}
}
/* ----- Clear selections in the listbox ----- */
static void ClearAllSelections(DFWINDOW wnd)
{
if (DfIsMultiLine(wnd) && wnd->SelectCount > 0) {
int sel;
for (sel = 0; sel < wnd->wlines; sel++)
ClearSelection(wnd, sel);
}
}
/* ----- Invert a selection in the listbox ----- */
static void FlipSelection(DFWINDOW wnd, int sel)
{
if (DfIsMultiLine(wnd)) {
if (DfItemSelected(wnd, sel))
ClearSelection(wnd, sel);
else
SetSelection(wnd, sel);
}
}
static int ExtendSelections(DFWINDOW wnd, int sel, int shift)
{
if (shift & (DF_LEFTSHIFT | DF_RIGHTSHIFT) &&
wnd->AnchorPoint != -1) {
int i = sel;
int j = wnd->AnchorPoint;
int rtn;
if (j > i)
swap(i,j);
rtn = i - j;
while (j <= i)
SetSelection(wnd, j++);
return rtn;
}
return 0;
}
static void SetSelection(DFWINDOW wnd, int sel)
{
if (DfIsMultiLine(wnd) && !DfItemSelected(wnd, sel)) {
char *lp = DfTextLine(wnd, sel);
*lp = DF_LISTSELECTOR;
wnd->SelectCount++;
}
}
static void ClearSelection(DFWINDOW wnd, int sel)
{
if (DfIsMultiLine(wnd) && DfItemSelected(wnd, sel)) {
char *lp = DfTextLine(wnd, sel);
*lp = ' ';
--wnd->SelectCount;
}
}
BOOL DfItemSelected(DFWINDOW wnd, int sel)
{
if (sel != -1 && DfIsMultiLine(wnd) && sel < wnd->wlines) {
char *cp = DfTextLine(wnd, sel);
return (int)((*cp) & 255) == DF_LISTSELECTOR;
}
return FALSE;
}
#endif
static void ChangeSelection(DFWINDOW wnd,int sel,int shift)
{
if (sel != wnd->selection) {
#ifdef INCLUDE_EXTENDEDSELECTIONS
if (DfIsMultiLine(wnd)) {
int sels;
if (!wnd->AddMode)
ClearAllSelections(wnd);
sels = ExtendSelections(wnd, sel, shift);
if (sels > 1)
DfSendMessage(wnd, DFM_PAINT, 0, 0);
if (sels == 0 && !wnd->AddMode) {
ClearSelection(wnd, wnd->selection);
SetSelection(wnd, sel);
wnd->AnchorPoint = sel;
}
}
#endif
WriteSelection(wnd, wnd->selection, FALSE, NULL);
wnd->selection = sel;
WriteSelection(wnd, sel, TRUE, NULL);
}
}
/* EOF */