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

📄 listbox.c

📁 dos 1.0 其中包含quick basic源代码、内存管理himem emm386 发展历史
💻 C
📖 第 1 页 / 共 3 页
字号:
WORD fRedraw;
	{
#ifdef LISTBOX_DIR
	if (!(pwnd->style & LBS_SORT))
		{
		/* not sorted : we must fit it in !!! */
		InsertSz(pwnd, pwnd->cszLb, sz, TRUE, fRedraw);
		}
	else if (pwnd->cszLb == 0)
		{
		/* first element in sorted listbox */
		InsertSz(pwnd, 0, sz, FALSE, fRedraw);
		}
	else
		{
		/* insert in sorted (no OnDemand concerns) */
		char FAR * lgpsz;
		WORD FAR * lmpiszoff;
		short	iszLo, iszHi;

		Assert(sz != NULL);		/* on-demand not allowed */

		lgpsz = LpvDeref(pwnd->hmemGpszLb);
		lmpiszoff = LpvDeref(pwnd->hmemMpiszoffLb);
		iszLo = iszMin;
		iszHi = pwnd->cszLb;
		do
			{
			REG short iszProbe = (iszLo + iszHi) / 2;

#ifdef KANJI
			if (fdircmp((char *) sz, lgpsz+lmpiszoff[iszProbe]) > 0)
#else
			if (fstrcmp((char *) sz, lgpsz+lmpiszoff[iszProbe]) > 0)
#endif
				iszLo = iszProbe+1;
			else
				iszHi = iszProbe;
			}
		while (iszLo < iszHi);

		/*GlobalUnlock(pwnd->hmemGpszLb);*/
		/*GlobalUnlock(pwnd->hmemMpiszoffLb);*/

		InsertSz(pwnd, iszLo, sz, FALSE, fRedraw);
		}
#else
	/* no DIR listboxes -- don't bother with sort option */
	Assert(!(pwnd->style & LBS_SORT));
	InsertSz(pwnd, pwnd->cszLb, sz, FALSE, fRedraw);	/* add at end */
#endif
	}

#ifdef KANJI
STATIC int
/*
 * it is not for KANJI.
 * sorting dirname as same as WINDOWS.
 *  order is as follows
 *  1: x.xxx	files
 *  2: [..]	parent directory
 *  3: [xxx]	directories
 *  4: [-x-]	drives
 */
fdircmp(s1, s2)
char FAR *s1, FAR *s2;
{
	if (*s1 != '[') {
		if (*s2 == '[') return(-1);
	} else if (*s2 != '[') {
		return(1);
	} else {
		++s1, ++s2;
		if (*s1 == '.') return(-1);
		if (*s2 == '.') return(1);
		if (*s1 != '-') {
			if (*s2 == '-') return(-1);
		} else  if (*s2 != '-') return(1);
	}
#ifdef KANJI
	return(fjstrcmp(s1, s2)); /* really needs for KANJI */
#else
	return(fstrcmp(s1, s2));
#endif
}

#define	iskanji(c)	( ((c)>=0x81 && (c)<=0x9F)||((c)>=0xE0 && (c)<= 0xFC) )

STATIC int
fjstrcmp(s1, s2)
unsigned char FAR *s1, FAR *s2;
{
	register unsigned short c1, c2;

	for (;;) {
		c1 = *s1++;
		if (iskanji(c1))
			c1 = (*s1 == 0)? 0: (c1 << 8)|*s1++;
		c2 = *s2++;
		if (iskanji(c2))
			c2 = (*s2 == 0)? 0: (c2 << 8)|*s2++;

		if (c1 < c2) return(-1);
		if (c1 > c2) return(1);
		if (c1 == 0) return(0);
	}
}

#endif /* KANJI */


STATIC VOID
InsertSz(pwnd, isz, sz, fForce, fRedraw)
/*
  -- insert a string at the specified position in the listbox
  -- if no memory left, do not add (no error condition)
  -- if sz == NULL, mark as special (on-demand)
  -- if previous position empty, replace string
  -- if changing size and fForce and no memory then go to low memory case
	(free any blocks and do everything on demand)
*/
REG PWND pwnd;
WORD isz;
char *sz;
BOOL fForce;
WORD fRedraw;
	{
	WORD FAR * lmpiszoff;		/* string pointers */
	WORD	cch;
	WORD	off;
	RRC	rrc;

	cch = (sz != NULL) ? (strlen(sz) + 1) : 0;
	if (pwnd->cszLb == 0)
		{
		/* first time allocation */
		Assert(pwnd->hmemGpszLb == NULL);
		Assert(pwnd->hmemMpiszoffLb == NULL);

		if ((pwnd->hmemGpszLb = GlobalAlloc(GMEM_MOVEABLE,
		    (DWORD) cbInitLb)) == NULL)
			{
			/* out of memory for string data */
			if (!fForce)
				return;
			/* force => no handle on demand all the time */
			}
		else if ((pwnd->hmemMpiszoffLb = GlobalAlloc(GMEM_MOVEABLE,
		    (DWORD) coffInitLb * sizeof(WORD))) == NULL)
			{
			/* out of memory for string indices */
			GlobalFree(pwnd->hmemGpszLb);
			pwnd->hmemGpszLb = NULL;
			if (!fForce)
				return;
			}
		/* initialize it */
		pwnd->offLb = 0;
		pwnd->iszTopLb = iszMin;
		pwnd->offMaxLb = cbInitLb;
		pwnd->iszMacLb = coffInitLb;
		pwnd->iszCurLb = iszMin;	/* start at top */
		}

	if (pwnd->hmemGpszLb == NULL)
		{
		/* we are doing things on demand */
		if (fForce)
			RevertToOomLb(pwnd, isz);
		return;
		}

	/* try to insert into the cache */
	Assert(pwnd->hmemGpszLb != NULL);
	Assert(pwnd->hmemMpiszoffLb != NULL);

	if (pwnd->cszLb >= pwnd->iszMacLb)
		{
		/* try to grow for indices */
		/* if >64K then request to GlobalReAlloc should fail! */
		WORD	hmem;

		if ((hmem = GlobalReAlloc(pwnd->hmemMpiszoffLb,
		    (DWORD) (pwnd->iszMacLb + coffGrowLb) * sizeof(WORD),
		    GMEM_MOVEABLE)) == NULL)
			{
			if (fForce)
				RevertToOomLb(pwnd, isz);
			return;
			}

		pwnd->iszMacLb += coffGrowLb;
		pwnd->hmemMpiszoffLb = hmem;
		}

	if (((off = pwnd->offLb) + cch) >= pwnd->offMaxLb)
		{
		WORD	hmem;

		if ((hmem = GlobalReAlloc(pwnd->hmemGpszLb,
		    (DWORD) pwnd->offMaxLb + cbGrowLb,
		    GMEM_MOVEABLE)) == NULL)
			{
			if (fForce)
				RevertToOomLb(pwnd, isz);
			return;
			}
		pwnd->offMaxLb += cbGrowLb;
		pwnd->hmemGpszLb = hmem;
		}

	/* now place in cache */
	if (sz == NULL)
		{
		off = offEmpty;
		}
	else
		{
		char FAR * lgpsz;		/* string data */

		lgpsz = LpvDeref(pwnd->hmemGpszLb);
		bltbytex((char FAR *) sz, lgpsz+off, cch);
		/*GlobalUnlock(pwnd->hmemGpszLb);*/
		}

	/* Insert offset into list */
	lmpiszoff = LpvDeref(pwnd->hmemMpiszoffLb);
	if (isz >= pwnd->cszLb)
		{
		/* easy insertion at end of list */
		lmpiszoff[pwnd->cszLb++] = off;
		}
	else
		{
		/* may be empty ? */
		WORD FAR * lpoff;

		lpoff = &lmpiszoff[isz];		/* where it should go */

		if (*lpoff != offEmpty)
			{
			/* move space in index block */
			bltbytex(lpoff, lpoff+1,
			    (pwnd->cszLb - isz) * sizeof(WORD));
			pwnd->cszLb++;

			/* if string was added before visible portion, update
			*   listbox indices (for top and current) */
			if (isz < pwnd->iszTopLb)
				{
				pwnd->iszTopLb++;
				pwnd->iszCurLb++;
				}
			}
		Debug(else Assert(off != offEmpty));
			/* else just replacing current on-demand string */

		*lpoff = off;
		}

	GetClientRrc(pwnd,&rrc);

	if ((isz >= pwnd->iszTopLb)
		 && (isz <= pwnd->iszTopLb + (WORD) rrc.ryBottom) && fRedraw)
		DrawWindow(pwnd);

	/*GlobalUnlock(pwnd->hmemMpiszoffLb);*/
	pwnd->offLb += cch;
	}

STATIC VOID
DeleteSz(pwnd, isz, fRedraw)
/*
  -- delete a string at the specified position in the listbox
*/
REG PWND pwnd;
WORD isz;
WORD fRedraw;
	{
	char FAR * lgpsz;		/* string data */
	WORD FAR * lmpiszoff;		/* string pointers */
	WORD	cch;
	WORD	off;
	WORD	offOld;
	WORD	iszLoop;
	WORD FAR * lpoff;
	RRC	rrc;


	Assert((isz >= 0) && (isz < pwnd->cszLb));

	/* try to insert into the cache */
	Assert(pwnd->hmemGpszLb != NULL);
	Assert(pwnd->hmemMpiszoffLb != NULL);

	lgpsz = LpvDeref(pwnd->hmemGpszLb);
	lmpiszoff = LpvDeref(pwnd->hmemMpiszoffLb);
	off = lmpiszoff[isz];

	Assert(off != offEmpty);	/* can't be on-demand */

	cch = fstrlen(lgpsz+off);
	bltbytex(lgpsz+off+cch,lgpsz+off,(pwnd->offLb-off-cch));
	pwnd->offLb -= cch;

	lpoff = &lmpiszoff[isz];		/* where it is */

	if (isz != pwnd->cszLb) bltbytex(lpoff+1, lpoff,
			    (pwnd->cszLb - isz) * sizeof(WORD));
	pwnd->cszLb--;

	for (iszLoop = 0; iszLoop < pwnd->cszLb; iszLoop++)
		{
		if ((offOld = lmpiszoff[iszLoop]) >= off)
			lmpiszoff[iszLoop] = offOld-cch;
		}

	GetClientRrc(pwnd,&rrc);

	if (pwnd->cszLb == 0)
		{
		SendMessage(pwnd,LB_RESETCONTENT,0,0L);
		}
	else
		{
		if (isz < pwnd->iszTopLb)
			{
			pwnd->iszTopLb--;
			if (pwnd->iszCurLb > 0) pwnd->iszCurLb--;
			}

		if (pwnd->iszCurLb >= pwnd->cszLb)
			pwnd->iszCurLb--;
		if ((pwnd->iszTopLb > 0)
			&&(pwnd->iszTopLb + (WORD) rrc.ryBottom > pwnd->cszLb))
			pwnd->iszTopLb--;
		}

	if ((isz >= pwnd->iszTopLb)
		 && (isz <= pwnd->iszTopLb + (WORD) rrc.ryBottom) && fRedraw)
		DrawWindow(pwnd);

	}



STATIC VOID
ReplaceSz(pwnd, isz, sz)
/*
  -- replace a string in the listbox
  -- update the screen if necessary
*/
REG PWND pwnd;
WORD isz;
char *sz;
	{
	char FAR * lgpsz;
	WORD FAR * lmpiszoff;
	WORD	off;
	RY	ry;
	RRC	rrc;

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


	Assert(isz < pwnd->cszLb);

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

	GetClientRrc(pwnd,&rrc);

	if ((isz >= pwnd->iszTopLb)
		 && (isz < pwnd->iszTopLb + (WORD) rrc.ryBottom))
		{
		/* item is displayed */
		ry = (RY) (isz - pwnd->iszTopLb);
		TextOut(pwnd, rxListBoxMin, ry, sz, -1, isaListBox);
		if (isz == pwnd->iszCurLb && FSelected(pwnd))
			{
			rrc.ryBottom = (rrc.ryTop = ry) + 1;
			FillRrc(pwnd, &rrc, '\0', DiMake(dmAttrOnly,
				pwnd->isaHiliteColor));
			}
		}
	}




STATIC VOID
RevertToOomLb(pwnd, isz)
/*
  -- revert to low memory useage of listbox data
    (both handles NULL, all data by on-demand)
  -- must not be sorted
*/
REG PWND pwnd;
WORD	isz;		/* string that is inserted */
	{
	Assert(!(pwnd->style & LBS_SORT));

	if (pwnd->hmemGpszLb != NULL)
		{
		GlobalFree(pwnd->hmemGpszLb);
		Assert(pwnd->hmemMpiszoffLb != NULL);
		GlobalFree(pwnd->hmemMpiszoffLb);
		pwnd->hmemGpszLb = NULL;
		pwnd->hmemMpiszoffLb = NULL;
		}
	/* if the new string is after the end of the listbox, adjust size */
	if (isz >= pwnd->cszLb)
		pwnd->cszLb = isz + 1;
	}




PRIVATE WORD FARPRIVATE
GetListText(pwnd, sz, cchMax)
/*
  -- fill sz with the contents of the currently selected string
  -- return number of characters copied
*/
REG PWND pwnd;
char *sz;
WORD cchMax;
	{
	char FAR * lgpsz;
	WORD FAR * lmpiszoff;
	char FAR * lsz;
	WORD	cch;
	char	szBuff[cchListTextMax];

	/* don't copy anything if the listbox is empty or cursor is not
	   on anything. */

	if (pwnd->cszLb == 0 || !FSelected(pwnd))
		{
		sz[0] = '\0';
		return (0);
		}

	if (pwnd->hmemGpszLb != NULL)
		{
		/* get from cache */
		lgpsz = LpvDeref(pwnd->hmemGpszLb);
		lmpiszoff = LpvDeref(pwnd->hmemMpiszoffLb);
		Assert(lmpiszoff[pwnd->iszCurLb] != offEmpty);
		lsz = (char FAR *) lgpsz + lmpiszoff[pwnd->iszCurLb];
		/*GlobalUnlock(pwnd->hmemMpiszoffLb);*/
		}
	else
		{
		GetOnDemand(pwnd, pwnd->iszCurLb, NULL, NULL, szBuff);
		lsz = (char FAR *) szBuff;
		}

	if ((cch = fstrlen(lsz) + 1) > cchMax)
		cch = cchMax;
	/* copy on the number of characters needed */
	bltbytex(lsz, (char FAR *) sz, cch);

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



STATIC VOID
GetOnDemand(pwnd, isz, plmpiszoff, plgpsz, szDest)
/*
  -- get a string for an on-demand listbox
  -- unlock the blocks, call listbox proc, relock the block
  -- fill szDest with string
  -- save string (so we don't have to go through this again) if room
*/
REG PWND pwnd;
WORD	isz;
WORD FAR ** plmpiszoff;
char FAR ** plgpsz;
char *	szDest;
	{
	/*GlobalUnlock(pwnd->hmemGpszLb);*/
	/*GlobalUnlock(pwnd->hmemMpiszoffLb);*/

	(*PwfnCtlLb(pwnd))(tmmText, szDest, isz, pwnd->id, 0, 0);

	if (pwnd->cszLb == 0 || pwnd->hmemGpszLb)
		{
		/* starting a new listbox or not oom listbox */
		InsertSz(pwnd, isz, szDest, FALSE, FALSE); /* may fail */
		}

	*plgpsz = LpvDeref(pwnd->hmemGpszLb);
	*plmpiszoff = LpvDeref(pwnd->hmemMpiszoffLb);
	}



STATIC VOID FAR *
LpvDeref(hmem)
/*
  -- defererence a handle
  -- (or return NULL if handle is NULL)
*/
WORD	hmem;
	{
	return (hmem == NULL) ? NULL : LpvGlobalDeref(hmem);
	}

/**************************************************************************/
/*   Public interface for listboxes                                       */
/**************************************************************************/

#ifndef LISTBOX_HORIZ	// only supported for vertical

PUBLIC VOID	FARPUBLIC
InitListBox(pwnd, pwfn_ctl)
PWND	 pwnd;
PWFN_CTL pwfn_ctl;
/*
  -- fix color
  -- put on demand function supplied into the wnd struct
  -- reset listbox
  -- fill listbox
*/
	{
	StartPublic();

		/* Non-directory ListBox */
	WORD	isz;
	WORD	csz;
	char	szBuffer[cchListTextMax];

	if (pwfn_ctl != NULL) PwfnCtlLb(pwnd) = pwfn_ctl;
	pwfn_ctl = PwfnCtlLb(pwnd);

	SendMessageShort(pwnd, LB_RESETCONTENT);
	csz = (*pwfn_ctl)(tmmCount, NULL, NULL, pwnd->id, 0, 0);
	isz = 0;

	if ((csz == cszUnknown)||(pwnd->style && LBS_SORT))
		{
		/* we must fill in the listbox */
		while (csz == cszUnknown || isz < csz)
			{
			if ((*pwfn_ctl)(tmmText, szBuffer, isz++, pwnd->id,
				    0, 0))
				{
				/* we have a string */
				SendMessage(pwnd, LB_ADDSTRING,
				    (WORD) szBuffer, 0L);
				}
			else if (csz == cszUnknown)
				break;	/* stop filling */
			}
		}
	else
		{
		/* fill on demand (fill with empties) */
		Assert(csz != cszUnknown);
		while (csz--)
			SendMessage(pwnd, LB_ADDSTRING, 0, 0L);
		}

	StopPublic();

	}



PUBLIC VOID FARPUBLIC
GetListBoxOrientation(pwnd, pisz, pdisz)
PWND pwnd;
WORD * pisz;
WORD * pdisz;
	{
	*pisz = (WORD) SendMessage(pwnd, LB_GETCURSEL, 0, 0L);
	*pdisz = (*pisz == iszNil) ? 0 : (*pisz - pwnd->iszTopLb);
	}



PUBLIC VOID	FARPUBLIC
InitListBoxOriented(pwnd, pwfn_ctl, pisz, pdisz)
PWND	 pwnd;
PWFN_CTL pwfn_ctl;
WORD	* pisz;			/* current selection */
WORD	* pdisz;		/* distance from top of box */
/*
  -- Init then orient listbox
*/
	{
	StartPublic();

	InitListBox(pwnd, pwfn_ctl);

	if (*pisz != iszNil) 
		{
		if (pwnd->cszLb == 0)
			{
			*pisz = iszNil;
			*pdisz = 0;
			}
		else
			{
			RRC	rrc;
			WORD	dry;

			GetClientRrc(pwnd,&rrc);
			dry = (WORD) rrc.ryBottom;

			/* 1 - make selection legal
			   2 - make sure no blank space at the bottom
			   3 - make distance from top legal */

			*pisz  = min(*pisz, pwnd->cszLb - 1);
			if (pwnd->cszLb + *pdisz < *pisz + dry)
				*pdisz = *pisz + dry - pwnd->cszLb;
			*pdisz = min(*pisz, min(*pdisz, dry-1));

			pwnd->iszTopLb = *pisz - *pdisz;
			pwnd->iszCurLb = *pisz;
			}
		}

	DrawWindow(pwnd);
	SendMessage(pwnd,LB_SETCURSEL,*pisz,0L);

	StopPublic();
	}

#endif /*!LISTBOX_HORIZ*/

⌨️ 快捷键说明

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