void TInputLine::draw()
{
    int l, r;
    TDrawBuffer b;

    uchar color = (state & sfFocused) ? getColor( 2 ) : getColor( 1 );

    b.moveChar( 0, ' ', color, size.x );
    char buf[256];
    strncpy( buf, data+firstPos, size.x - 2 );
    buf[size.x - 2 ] = EOS;
    b.moveStr( 1, buf, color );

    if( canScroll(1) )
        b.moveChar( size.x-1, rightArrow, getColor(4), 1 );
    if( (state & sfSelected) != 0 )
        {
        if( canScroll(-1) )
            b.moveChar( 0, leftArrow, getColor(4), 1 );
        l = selStart - firstPos;
        r = selEnd - firstPos;
        l = max( 0, l );
        r = min( size.x - 2, r );
        if (l <  r)
            b.moveChar( l+1, 0, getColor(3), r - l );
        }
    writeLine( 0, 0, size.x, size.y, b );
    setCursor( curPos-firstPos+1, 0);
}
/*
 * Return the current object under the certain point
 */
HIT CNOutBarCtrl::hitTest(const CPoint &pt)
{
	int obj = HT_NONE;
	int index = -1;
	CRect rcClient, rc;
	GetClientRect(rcClient);
	getInsideRect(rc);

	if (!rc.PtInRect(pt)) {
		if (pt.y >= 0 && pt.y < rc.top) {
			obj = HT_FOLDER;
			index = (pt.y - 1) / FOLDER_HEIGHT;
		} else if (pt.y > rc.bottom && pt.y < rcClient.bottom - 1) {
			obj = HT_FOLDER;
			index = (pt.y - rc.bottom) / FOLDER_HEIGHT + selFolder + 1;
		}
	} else {
		for (int i = 0; i < 2; i++) {
			if (canScroll(i)) {
				CRect rcScroll;
				getScrollRect(rcScroll, i);
				if (rcScroll.PtInRect(pt))
					return MAKEHIT(HT_SCROLL, i);
			}
		}

		if (largeIconView) {
			int offset = (rc.Width() - LARGE_ICON_W) / 2;
			if (pt.x >= rc.left + offset &&
				pt.x <= rc.right - offset) {
				int y = pt.y - rc.top;
				offset = y % LARGE_ITEM_H - ICON_OFFSET;
				if (offset >= 0 && offset <= LARGE_ICON_H) {
					int i = y / LARGE_ITEM_H + scrollPos();
					if (i <= getMaxVisibleItem()) {
						obj = HT_ITEM;
						index = i;
					}
				}
			}
		} else if (pt.x < SMALL_ICON_W + 32) {
			int i = (pt.y - rc.top) / SMALL_ITEM_H + scrollPos();
			if (i <= getMaxVisibleItem()) {
				obj = HT_ITEM;
				index = i;
			}
		}
	}
	
	return MAKEHIT(obj, index);
}
BOOL CNOutBarCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
	int dir;
	int delta = zDelta / WHEEL_DELTA;
	
	if (delta > 0)
		dir = SCROLL_DIR_UP;
	else {
		dir = SCROLL_DIR_DOWN;
		delta = -delta;
	}
	if (canScroll(dir))
		scroll(dir, delta);

	return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}
void CNOutBarCtrl::scroll(int dir, int delta)
{
	if (dir == SCROLL_DIR_UP)
		scrollPos() -= delta;
	else
		scrollPos() += delta;

	if (!canScroll(dir)) {
		KillTimer(IDT_SCROLL);
			
		CClientDC dc(this);
		drawScroll(&dc, dir);
		pressedHit = lastHit = HITNONE;
	}
		
	repaintInsideRect();
}
void CNOutBarCtrl::drawAll(CDC *pDC)
{
	CDC memDC;
	memDC.CreateCompatibleDC(pDC);
	CRect rcClient;
	GetClientRect(rcClient);
	CBitmap bm;
	bm.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height());
	CBitmap *oldBitmap = memDC.SelectObject(&bm);

	int obj = HITOBJ(lastHit);
	int index = HITINDEX(lastHit);

	int i;
	for (i = folders.size() - 1; i >= 0; i--)
		drawFolder(&memDC, i, FALSE, (obj == HT_FOLDER && index == i));

	CRect rc;
	getInsideRect(rc);
	drawBackground(&memDC, rc);

	CRgn rgn;
	rgn.CreateRectRgnIndirect(rc);
	memDC.SelectClipRgn(&rgn);

	int max = getMaxVisibleItem();
	for (i = scrollPos(); i <= max; i++)
		drawItem(&memDC, i);

	if (obj == HT_ITEM)
		hilightItem(&memDC, index, FALSE);

	for (i = 1; i >= 0; i--) {
		if (canScroll(i))
			drawScroll(&memDC, i, pressedHit == MAKEHIT(HT_SCROLL, i));
	}

	pDC->BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY);

	memDC.SelectObject(oldBitmap);
}
void  TInputLine::handleEvent( TEvent& event )
{
    TView::handleEvent(event);

    int delta, anchor, i;
    if( (state & sfSelected) != 0 )
        switch( event.what )
            {
            case  evMouseDown:
                if( canScroll(delta = mouseDelta(event)) )
                    do  {
                        if( canScroll(delta) )
                            {
                            firstPos += delta;
                            drawView();
                            }
                        } while( mouseEvent( event, evMouseAuto ) );
                else if (event.mouse.doubleClick)
                        selectAll(True);
                else
                    {
                    anchor =  mousePos(event);
                    do  {
                        if( event.what == evMouseAuto &&
                            canScroll( delta = mouseDelta(event) )
                          )
                            firstPos += delta;
                        curPos = mousePos(event);
                        if( curPos < anchor )
                            {
                            selStart = curPos;
                            selEnd = anchor;
                            }
                        else
                            {
                            selStart = anchor;
                            selEnd = curPos;
                            }
                        drawView();
                        } while (mouseEvent(event, evMouseMove | evMouseAuto));
                    }
                clearEvent(event);
                break;
            case  evKeyDown:
                switch( ctrlToArrow(event.keyDown.keyCode) )
                    {
                    case kbLeft:
                        if( curPos > 0 )
                            curPos--;
                        break;
                    case kbRight:
                        if( curPos < strlen(data) )
                            curPos++;
                        break;
                    case kbHome:
                        curPos =  0;
                        break;
                    case kbEnd:
                        curPos = strlen(data);
                        break;
                    case kbBack:
                        if( curPos > 0 )
                            {
                            strcpy( data+curPos-1, data+curPos );
                            curPos--;
                            if( firstPos > 0 )
                                firstPos--;
                            }
                        break;
                    case kbDel:
                        if( selStart == selEnd )
                            if( curPos < strlen(data) )
                                {
                                selStart = curPos;
                                selEnd = curPos + 1;
                                }
                        deleteSelect();
                        break;
                    case kbIns:
                        setState(sfCursorIns, Boolean(!(state & sfCursorIns)));
                        break;
                    default:
                        if( event.keyDown.charScan.charCode >= ' ' )
                            {
                            if( (state & sfCursorIns) != 0 )
                                strcpy( data + curPos, data + curPos + 1 );
                            else
                                deleteSelect();
                            if( strlen(data) < maxLen )
                                {
                                if( firstPos > curPos )
                                    firstPos = curPos;
                                memmove( data + curPos + 1, data + curPos,
                                         strlen(data+curPos)+1 );
                                data[curPos++] =
                                    event.keyDown.charScan.charCode;
                                }
                            }
                        else if( event.keyDown.charScan.charCode == CONTROL_Y)
                            {
                            *data = EOS;
                            curPos = 0;
                            }
                        else
                            return;
                    }
                    selStart = 0;
                    selEnd = 0;
                    if( firstPos > curPos )
                        firstPos = curPos;
                    i = curPos - size.x + 3;
                    if( firstPos < i )
                        firstPos = i;
                    drawView();
                    clearEvent( event );
                    break;
            }
}