⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 listbox.c

📁 Dos6.0
💻 C
📖 第 1 页 / 共 3 页
字号:
RY	ryTop;
RY	ryBottom;
WORD	isz;
	{
	char	sz[cchListTextMax];
	char FAR * lgpsz;
	WORD FAR * lmpiszoff;
	REG RY	ry;
#ifdef LISTBOX_HORIZ
	WORD	ccol;			/* # of columns */
	RX	rxLeft;			/* current left position */
#endif

	/* lock down string buffer and indexes (handles may be NULL) */
	lgpsz = LpvDeref(pwnd->hmemGpszLb);
	lmpiszoff = LpvDeref(pwnd->hmemMpiszoffLb);

	BeginDraw();

#ifdef LISTBOX_HORIZ
	/* Horizontal : fill in vertical list, then go to the right */
	ccol = pwnd->citemWidthLb;
	Assert(ccol != 0);
	rxLeft = RxLeftItem(pwnd, 0);
	while (ccol--)
		{
		WORD	cch;
#endif /*LISTBOX_HORIZ*/
		for (ry = ryTop; ry < ryBottom; ry++)
			{
			WORD	off;

			if (isz >= pwnd->cszLb)
				{
#ifndef LISTBOX_HORIZ
				break;		/* gone too far */
#else
				cch = 0;
				goto BlankFillItem;
#endif /*LISTBOX_HORIZ*/
				}

			if (pwnd->hmemGpszLb != NULL &&
			    (off = lmpiszoff[isz]) != offEmpty)
				{
				/* valid cached string */
				fstrcpy((char FAR *) sz, lgpsz+off);
				}
			else
				{
				/* not in cache */
				GetOnDemand(pwnd, isz, &lmpiszoff, &lgpsz, sz);
				}

#ifndef LISTBOX_HORIZ
			TextOut(pwnd, rxListBoxMin, ry, sz, -1, pwnd->isaColor);
#else
			/* display the string in proper column */
			if ((cch = CchRealLenSz(sz)) > pwnd->drxItemLb)
				cch = pwnd->drxItemLb;
			TextOut(pwnd, rxLeft, ry, sz, cch, pwnd->isaColor);
BlankFillItem:
			if (cch != pwnd->drxItemLb)
				{
				/* fill remaining part of line */
				RRC	rrc;

				rrc.rxLeft = rxLeft + cch;
				rrc.rxRight = rxLeft + pwnd->drxItemLb;
				rrc.ryBottom = (rrc.ryTop = ry) + 1;
				FillRrc(pwnd, &rrc, ' ', pwnd->isaColor);
				}
#endif /*LISTBOX_HORIZ*/

			/* invert the listbox selection */
			if (isz == pwnd->iszCurLb && FSelected(pwnd))
				{
				/* selected */
				RRC	rrc;

#ifndef LISTBOX_HORIZ
				/* entire width of listbox */
				GetClientRrc(pwnd, &rrc);
#else
				/* just this item with 1 before & after */
				rrc.rxRight = (rrc.rxLeft = rxLeft - 1) +
				   pwnd->drxItemLb + 2;
#endif
				rrc.ryBottom = (rrc.ryTop = ry) + 1;
				FillRrc(pwnd, &rrc, '\0', DiMake(dmAttrOnly,
				    pwnd->isaHiliteColor));
				}

			isz++;
			}
#ifdef LISTBOX_HORIZ
		rxLeft += (BYTE) pwnd->drxItemLb + 1;
		}/*end while(ccol--); */
#endif

	EndDraw();

	/* unlock string buffers and indexes */
	/*GlobalUnlock(pwnd->hmemGpszLb);*/
	/*GlobalUnlock(pwnd->hmemMpiszoffLb);*/
	}



STATIC VOID
ScrollListBox(pwnd, dry, fKillOld)
/*
  -- scroll vertical listbox by dry lines (may be negative)
  -- if hit top show top, if hit bottom show bottom
*/
REG PWND pwnd;
short	dry;
BOOL	fKillOld;	/* TRUE => kill old selection */
	{
	WORD	iszTop;
	RRC	rrc;
	WORD	iszBottom;
	short	iszNewTop;
	short	iszNewBottom;	/* note : use for signed compares */
	WORD	ryBottom;

#ifdef LISTBOX_HORIZ
	if (pwnd->style & WS_HSCROLL)
		{
		// horizontal listbox
		Assert(!fKillOld);
		ScrollHorizListBox(pwnd, dry);
		return;
		}
#endif /*LISTBOX_HORIZ*/
	iszTop = pwnd->iszTopLb;

	/* optionally turn off old selection */
	if (fKillOld)
		HiliteListSel(pwnd, FALSE);	/* turn off old */

	GetClientRrc(pwnd, &rrc);
	ryBottom = rrc.ryBottom;
	iszBottom = iszTop + ryBottom - 1;
	iszNewTop = iszTop + dry;
	iszNewBottom = iszBottom + dry;

	/* see if we should stop at top or bottom */
	if (iszNewTop < 0)
		{
		iszNewTop = iszMin;
		iszNewBottom = ryBottom - 1;
		}
	else if (iszNewBottom >= pwnd->cszLb)
		{
		iszNewBottom = pwnd->cszLb - 1;
		if ((iszNewTop = iszNewBottom - (ryBottom - 1)) < 0)
			iszNewTop = iszMin;
		}

	dry = iszNewTop - iszTop;
	/* move selection if necessary */
	if (pwnd->iszCurLb > iszNewBottom)
		pwnd->iszCurLb = iszNewBottom;
	else if (pwnd->iszCurLb < iszNewTop)
		pwnd->iszCurLb = iszNewTop;

	pwnd->iszTopLb = iszNewTop;

	/* smooth scroll */
	if (iszNewTop > iszTop && iszNewTop < iszBottom)
		{
		BltRrc(pwnd, 0, 0, rrc.rxRight, (BYTE) (ryBottom - dry),
		    0, (BYTE) dry);
		rrc.ryTop = (RY) (ryBottom-dry);
		FillRrc(pwnd, &rrc, ' ', pwnd->isaColor);
		FillListBox(pwnd, rrc.ryTop, (RY) ryBottom, iszNewTop+rrc.ryTop);
		}
	else if (iszNewBottom > iszTop && iszNewBottom < iszBottom)
		{
		BltRrc(pwnd, 0, (RY) (0-dry), rrc.rxRight, (BYTE) (ryBottom + dry),
		    0, 0);
		rrc.ryBottom = (RY) (0-dry);
		FillRrc(pwnd, &rrc, ' ', pwnd->isaColor);
		FillListBox(pwnd, 0, (RY) (0-dry), iszNewTop);
		}
	else if (iszNewTop != iszTop)
		{
		/* outside range to scroll => redraw it */
		DisplayListBox(pwnd);
		}

	SetScrollWindow(pwnd);
	HiliteListSel(pwnd, TRUE);
	}


#ifdef LISTBOX_HORIZ

STATIC VOID
ScrollHorizListBox(pwnd, dcol)
/*
  -- scroll a horizontal listbox by dcol columns (may be negative)
  -- if hit top show first column, if hit bottom show last column
*/
REG PWND pwnd;
short	dcol;
	{
	WORD	iszTop;
	BYTE	dry;
	RRC	rrc;
	short	iszNewTop;	/* note : use for signed compares */

	Assert(pwnd->style & WS_HSCROLL);


	GetClientRrc(pwnd,&rrc);
	iszTop = pwnd->iszTopLb;
	dry = rrc.ryBottom;
	Assert(iszTop % dry == 0);
	
	iszNewTop = iszTop + dcol * dry;
	if (iszNewTop < 0)
		{
		pwnd->iszCurLb = iszNewTop = iszMin;
		}
	else if (iszNewTop >= pwnd->cszLb)
		{
		/* adjust to right hand side */
		iszNewTop = ((pwnd->cszLb - 1) / dry) * dry;
		pwnd->iszCurLb = pwnd->cszLb - 1;	/* select last */
		}

	pwnd->iszTopLb = iszNewTop;

	if (iszNewTop != iszTop)
		FillListBox(pwnd, 0, dry, pwnd->iszTopLb = iszNewTop);
	SetScrollWindow(pwnd);

	HiliteListSel(pwnd, TRUE);
	}
#endif /*LISTBOX_HORIZ*/



STATIC VOID
HiliteListSel(pwnd, fHilite)
/*
  -- highlight/unhighlight the iszCur in the listbox.
  -- if iszCur is not displayed force it to be displayed
*/
REG PWND pwnd;
BOOL	fHilite;	/* TRUE => hilite, FALSE => unhilite */
	{
	REG WORD iszCur;
	RRC	rrc;
#ifdef LISTBOX_HORIZ
	BYTE	dry;		/* height */
#endif

	iszCur = pwnd->iszCurLb;

	/* Cursor should be always on */
	Assert(pwnd->fCursorOn);
	/* position must be valid (assume < 32K) */
	Assert((short) iszCur >= 0);

	GetClientRrc(pwnd, &rrc);

#ifdef LISTBOX_HORIZ
	if (!(pwnd->style & WS_HSCROLL))
#endif
		{
		/* if out of visible range, scroll vertically into range */
		if (fHilite &&
		    (iszCur < pwnd->iszTopLb ||
		     iszCur >= (pwnd->iszTopLb +
		     CitemVisible(pwnd, rrc.ryBottom))))
			{
			/* shift visible range */
			if (iszCur > pwnd->cszLb -
			    CitemVisible(pwnd, rrc.ryBottom))
				pwnd->iszTopLb = pwnd->cszLb -
				    CitemVisible(pwnd, rrc.ryBottom);
			else
				pwnd->iszTopLb = iszCur;

			if (fDrawItem)
				DisplayListBox(pwnd);
			}
		/* Vertical : compute 1 whole line to be [un]highlighted */
		rrc.ryBottom = (rrc.ryTop = (RY) (iszCur - pwnd->iszTopLb)) + 1;

		Assert(rrc.rxLeft == 0);
		MoveCursor(pwnd, rxListBoxMin, rrc.ryTop);
		}

#ifdef LISTBOX_HORIZ
	else
		{
		Assert(pwnd->style & WS_HSCROLL);

		dry = rrc.ryBottom - rrc.ryTop;
		/* if out of visible range, scroll horizontally into range */
		if (fHilite && iszCur < pwnd->iszTopLb)
			{
			/* adjust to be at the left column */
			pwnd->iszTopLb = (iszCur / dry) * dry;
			if (fDrawItem)
				DisplayListBox(pwnd);
			}
		else if (fHilite &&
		    iszCur >= (pwnd->iszTopLb +
		     CitemVisible(pwnd, rrc.ryBottom)))
			{
			/* adjust to be at the right column */
			pwnd->iszTopLb = (iszCur / dry) * dry;
			if (pwnd->iszTopLb >= dry * (pwnd->citemWidthLb - 1))
				pwnd->iszTopLb -= dry * (pwnd->citemWidthLb - 1);
			if (fDrawItem)
				DisplayListBox(pwnd);
			}

		/* Horizontal : compute partial line to hilight */
		iszCur -= pwnd->iszTopLb;	/* from top of listbox */
		Assert((short)iszCur >= 0 &&
		    iszCur < CitemVisible(pwnd, rrc.ryBottom));

		rrc.ryBottom = (rrc.ryTop = (RY) (iszCur % dry)) + 1;

		/* width includes 1 space before and after */
		Assert(rxListBoxMin == 1);
		rrc.rxRight =
		    (rrc.rxLeft = RxLeftItem(pwnd, iszCur / dry) - 1) +
		      pwnd->drxItemLb + 2;

		MoveCursor(pwnd, rrc.rxLeft + rxListBoxMin, rrc.ryTop);
		}
#endif /*LISTBOX_HORIZ*/

	if (fDrawItem)
		{
		FillRrc(pwnd, &rrc, '\0', DiMake(dmAttrOnly,
		    fHilite ? pwnd->isaHiliteColor : pwnd->isaColor));
#ifdef LISTBOX_COLOR
		if (!fHilite)
			{
			/* refill the listbox to get correct colors */
			SetFSelected(pwnd, FALSE);	/* fake not selected */
			FillListBox(pwnd, rrc.ryTop, rrc.ryTop+1, iszCur);
			}
#endif
		}
	SetFSelected(pwnd, TRUE);
	}



STATIC VOID
MoveSelection(pwnd, iszNew)
/*
  -- move the selection to iszNew
*/
REG PWND pwnd;
WORD iszNew;
	{
	Assert(iszNew < pwnd->cszLb);

	if (pwnd->iszCurLb == iszNew && FSelected(pwnd))
		return;		/* already there */

	HiliteListSel(pwnd, FALSE);	/* turn old off */
	pwnd->iszCurLb = iszNew;
	HiliteListSel(pwnd, TRUE);
	}



STATIC VOID
MoveSelectionDown(pwnd)
/*
  -- move iszCur down a line
*/
REG PWND pwnd;
	{
	WORD	iszBottom;
	RRC	rrc;

	GetClientRrc(pwnd,&rrc);
	iszBottom = pwnd->iszTopLb + CitemVisible(pwnd, rrc.ryBottom) - 1;

	if (FSelected(pwnd) && pwnd->iszCurLb + 1 < pwnd->cszLb)
		{
		HiliteListSel(pwnd, FALSE);
		if (pwnd->iszCurLb++ == iszBottom)
			{
			ScrollListBox(pwnd, 1, FALSE);
			return;
			}
		}
	HiliteListSel(pwnd, TRUE);
	}



STATIC VOID
MoveSelectionUp(pwnd)
/*
  -- move iszCur up a line
*/
REG PWND pwnd;
	{
	if (FSelected(pwnd) && pwnd->iszCurLb != iszMin)
		{
		HiliteListSel(pwnd, FALSE);
		if (pwnd->iszCurLb-- == pwnd->iszTopLb)
			{
			ScrollListBox(pwnd, -1, FALSE);
			return;
			}
		}
	HiliteListSel(pwnd, TRUE);
	}



#ifdef LISTBOX_HORIZ
STATIC VOID
MoveSelectionLeft(pwnd, dcol)
/*
  -- move selection left "dcol" columns
  -- vertical listboxes => move up
*/
REG PWND pwnd;
WORD	dcol;
	{
	if (pwnd->style & WS_VSCROLL)
		{
		Assert(dcol == 1);
		MoveSelectionUp(pwnd);
		}
	else
		{
		// horizontal

		WORD	cszMove;	/* # strings to move selection by */
		RRC	rrc;

		GetClientRrc(pwnd,&rrc);
		cszMove = rrc.ryBottom * dcol;

		if (pwnd->iszCurLb - iszMin < cszMove)
			MoveSelection(pwnd, iszMin);
		else
			MoveSelection(pwnd, pwnd->iszCurLb - cszMove);
		}
	}



STATIC VOID
MoveSelectionRight(pwnd, dcol)
/*
  -- move selection right "dcol" columns (horizontal only)
  -- vertical listboxes => move down
*/
REG PWND pwnd;
WORD	dcol;
	{
	if (pwnd->style & WS_VSCROLL)
		{
		Assert(dcol == 1);
		MoveSelectionDown(pwnd);
		}
	else
		{
		WORD	iszNew;
		RRC	rrc;

		GetClientRrc(pwnd,&rrc);
		iszNew = pwnd->iszCurLb + rrc.ryBottom * dcol;
		if (iszNew >= pwnd->cszLb)
			MoveSelection(pwnd, pwnd->cszLb - 1);
		else
			MoveSelection(pwnd, iszNew);
		}
	}
#endif /*LISTBOX_HORIZ*/



STATIC BOOL
FLocateMatch(pwnd, wParam)
/*
  -- find the entry in the list box beginning with ch (case insensitive)
  -- move current location if found
  -- return TRUE if selection made
*/
REG PWND pwnd;
WORD	wParam;			/* wParam of WM_CHAR message */
	{
	char FAR * lgpsz;
	WORD FAR * lmpiszoff;
	REG WORD iszCur;
	BOOL	fRet;

	fRet = FALSE;

 	if (wParam > 0xff)
 		return FALSE;	/* non-ascii */
 
	iszCur = pwnd->iszCurLb;
	if (FSelected(pwnd))
		if (++iszCur >= pwnd->cszLb)
			iszCur = iszMin;	/* try from this point on */

	lgpsz = LpvDeref(pwnd->hmemGpszLb);
	lmpiszoff = LpvDeref(pwnd->hmemMpiszoffLb);

	/* convert to upper case */
	if ((char) wParam >= 'a' && (char) wParam <= 'z')
		wParam -= 'a' - 'A';
	else if (wParam > 0x7f)
		wParam = ChUpperFromChExt((char)wParam);

	do
		{
		char FAR * lgpsz2;
		char	ch2;
		WORD	off;

		if (pwnd->hmemGpszLb != NULL &&
		    (off = lmpiszoff[iszCur]) != offEmpty)
			{
			/* valid cached string */
			lgpsz2 = lgpsz+off;		/* &lgpsz[off] */
			}
		else
			{
			/* not in cache */
			char	szBuff[cchListTextMax];

			GetOnDemand(pwnd, iszCur, &lmpiszoff, &lgpsz, szBuff);
			lgpsz2 = (char FAR *) szBuff;
			}
#ifdef EXTRAS
		if (*lgpsz2 == chColorPrefix)
				lgpsz2 += 2;
#endif
		while (((unsigned char)(*lgpsz2) < '0') && (*lgpsz2 != '\0'))
			lgpsz2++;

		ch2 = *lgpsz2;

		if (ch2 >= 'a' && ch2 <= 'z')
			ch2 -= 'a' - 'A';
		else if ((unsigned char) ch2 > 0x7f)
			ch2 = ChUpperFromChExt(ch2);

		if (ch2 == (char) wParam)
			{
			/* got it */
			MoveSelection(pwnd, iszCur);
			fRet = TRUE;
			break;
			}

		/* move iszCur to next possibility */
		if (++iszCur >= pwnd->cszLb)
			iszCur = iszMin;	/* wrap around */

		}
	while (iszCur != pwnd->iszCurLb);

	/*GlobalUnlock(pwnd->hmemGpszLb);*/
	/*GlobalUnlock(pwnd->hmemMpiszoffLb);*/
	return (fRet);
	}




STATIC VOID
ResetContent(pwnd)
/*
  -- resets the contents of the list box
*/
REG PWND pwnd;
	{

#ifdef LISTBOX_HORIZ
	if (pwnd->citemWidthLb == 0)
		{
		RRC rrc;
		GetClientRrc(pwnd,&rrc);
		/* initialize horizontal listbox info */
		pwnd->citemWidthLb = 1;
		pwnd->drxItemLb = rrc.rxRight - 2;
			/* 2 extra for start and end space */
		}
#endif /*LISTBOX_HORIZ*/

	/* free any listbox data */
	if (pwnd->hmemGpszLb != NULL)
		{
		GlobalFree(pwnd->hmemGpszLb);
		Assert(pwnd->hmemMpiszoffLb != NULL);
		GlobalFree(pwnd->hmemMpiszoffLb);
		pwnd->hmemGpszLb = NULL;
		pwnd->hmemMpiszoffLb = NULL;
		}
	else
		{
		Assert(pwnd->hmemMpiszoffLb == NULL);
		}
	pwnd->cszLb = pwnd->iszTopLb = 0;
	pwnd->iszCurLb = iszMin;
	SetFSelected(pwnd, FALSE);
	/* set cursor to no selection */
	MoveCursor(pwnd, rxListBoxMin, 0);
	}


PRIVATE VOID FARPRIVATE
AddListString(pwnd, sz)
/*
  -- add an item to the list box
  -- if sz == NULL, mark as not yet known (for fill on-demand)
*/
REG PWND pwnd;
char *sz;
	{
	AddListSz(pwnd, sz, FALSE);
	}

PRIVATE VOID FARPRIVATE
AddListSz(pwnd, sz, fRedraw)
/*
  -- add an item to the list box
  -- if sz == NULL, mark as not yet known (for fill on-demand)
*/
REG PWND pwnd;
char *sz;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -