|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
// File : kvi_input.cpp
|
|
|
|
// Creation date : Sun Jan 3 1999 23:11:50 by Szymon Stefanek
|
|
|
|
//
|
|
|
|
// This file is part of the KVirc irc client distribution
|
|
|
|
// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot net)
|
|
|
|
//
|
|
|
|
// 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 opinion) 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. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
#define __KVIRC__
|
|
|
|
#define _KVI_DEBUG_CHECK_RANGE_
|
|
|
|
#include "kvi_debug.h"
|
|
|
|
|
|
|
|
#define _KVI_INPUT_CPP_
|
|
|
|
|
|
|
|
#include "kvi_options.h"
|
|
|
|
#include "kvi_app.h"
|
|
|
|
#include "kvi_settings.h"
|
|
|
|
#include "kvi_defaults.h"
|
|
|
|
#include "kvi_colorwin.h"
|
|
|
|
#include "kvi_texticonwin.h"
|
|
|
|
#include "kvi_window.h"
|
|
|
|
|
|
|
|
#include "kvi_locale.h"
|
|
|
|
#include "kvi_mirccntrl.h"
|
|
|
|
#include "kvi_userlistview.h"
|
|
|
|
#include "kvi_ircview.h"
|
|
|
|
#include "kvi_console.h"
|
|
|
|
#include "kvi_out.h"
|
|
|
|
#include "kvi_iconmanager.h"
|
|
|
|
#include "kvi_scripteditor.h"
|
|
|
|
#include "kvi_config.h"
|
|
|
|
#include "kvi_historywin.h"
|
|
|
|
#include "kvi_input.h"
|
|
|
|
#include "kvi_userinput.h"
|
|
|
|
#include "kvi_kvs_script.h"
|
|
|
|
#include "kvi_kvs_kernel.h"
|
|
|
|
#include "kvi_doublebuffer.h"
|
|
|
|
#include "kvi_styled_controls.h"
|
|
|
|
#include "kvi_texticonmanager.h"
|
|
|
|
#include "kvi_draganddrop.h"
|
|
|
|
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <tqfiledialog.h>
|
|
|
|
#include "kvi_tal_popupmenu.h"
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqclipboard.h>
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
#include "kvi_pointerlist.h"
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqclipboard.h>
|
|
|
|
#include <tqmessagebox.h>
|
|
|
|
#include "kvi_tal_hbox.h"
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqstyle.h>
|
|
|
|
#include <tqevent.h>
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef ACCEL_KEY
|
|
|
|
#define ACCEL_KEY(k) "\t" + TQString(TQKeySequence( TQt::CTRL | TQt::Key_ ## k ))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <tqcursor.h>
|
|
|
|
|
|
|
|
//This comes from kvi_app.cpp
|
|
|
|
extern KviColorWindow * g_pColorWindow;
|
|
|
|
extern KviTextIconWindow * g_pTextIconWindow;
|
|
|
|
extern KviHistoryWindow * g_pHistoryWindow;
|
|
|
|
extern KviTalPopupMenu * g_pInputPopup;
|
|
|
|
|
|
|
|
static TQFontMetrics * g_pLastFontMetrics = 0;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef COMPILE_PSEUDO_TRANSPARENCY
|
|
|
|
extern TQPixmap * g_pShadedChildGlobalDesktopBackground;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#define KVI_INPUT_MAX_GLOBAL_HISTORY_ENTRIES 100
|
|
|
|
#define KVI_INPUT_MAX_LOCAL_HISTORY_ENTRIES 20
|
|
|
|
|
|
|
|
|
|
|
|
extern KviInputHistory * g_pInputHistory;
|
|
|
|
|
|
|
|
|
|
|
|
KviInputHistory::KviInputHistory()
|
|
|
|
{
|
|
|
|
m_pStringList = new KviPointerList<TQString>;
|
|
|
|
m_pStringList->setAutoDelete(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
KviInputHistory::~KviInputHistory()
|
|
|
|
{
|
|
|
|
delete m_pStringList;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputHistory::add(TQString * s)
|
|
|
|
{
|
|
|
|
m_pStringList->insert(0,s);
|
|
|
|
if(m_pStringList->count() > KVI_INPUT_MAX_GLOBAL_HISTORY_ENTRIES)m_pStringList->removeLast();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputHistory::load(const char * filename)
|
|
|
|
{
|
|
|
|
KviConfig c(filename,KviConfig::Read);
|
|
|
|
|
|
|
|
int cnt = c.readIntEntry("Count",0);
|
|
|
|
|
|
|
|
if(cnt > KVI_INPUT_MAX_GLOBAL_HISTORY_ENTRIES)cnt = KVI_INPUT_MAX_GLOBAL_HISTORY_ENTRIES;
|
|
|
|
|
|
|
|
KviStr tmp;
|
|
|
|
|
|
|
|
for(int i=0;i<cnt;i++)
|
|
|
|
{
|
|
|
|
tmp.sprintf("S%d",i);
|
|
|
|
TQString entry = c.readTQStringEntry(tmp.ptr(),"");
|
|
|
|
if(!entry.isEmpty())add(new TQString(entry));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputHistory::save(const char * filename)
|
|
|
|
{
|
|
|
|
KviConfig c(filename,KviConfig::Write);
|
|
|
|
c.clear();
|
|
|
|
|
|
|
|
c.writeEntry("Count",m_pStringList->count());
|
|
|
|
|
|
|
|
KviStr tmp;
|
|
|
|
int idx = 0;
|
|
|
|
|
|
|
|
for(TQString * s = m_pStringList->first();s;s = m_pStringList->next())
|
|
|
|
{
|
|
|
|
if(!s->isEmpty())
|
|
|
|
{
|
|
|
|
tmp.sprintf("S%d",idx);
|
|
|
|
c.writeEntry(tmp.ptr(),*s);
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============== KviInputEditor ==============//
|
|
|
|
|
|
|
|
static int g_iInputFontCharWidth[256];
|
|
|
|
static bool g_bInputFontMetricsDirty = true;
|
|
|
|
|
|
|
|
|
|
|
|
KviInputEditor::KviInputEditor(TQWidget * par,KviWindow *wnd,KviUserListView * view)
|
|
|
|
:TQFrame(par,"input")
|
|
|
|
{
|
|
|
|
m_pIconMenu = 0;
|
|
|
|
m_pInputParent = par;
|
|
|
|
m_iMaxBufferSize = KVI_INPUT_MAX_BUFFER_SIZE;
|
|
|
|
m_iCursorPosition = 0; //Index of the char AFTER the cursor
|
|
|
|
m_iFirstVisibleChar = 0; //Index of the first visible character
|
|
|
|
m_iSelectionBegin = -1; //Index of the first char in the selection
|
|
|
|
m_iSelectionEnd = -1; //Index of the last char in the selection
|
|
|
|
m_bIMComposing = false; //Whether the input method is active (composing).
|
|
|
|
// for input method support
|
|
|
|
m_iIMStart = 0; //Index of the start of the preedit string.
|
|
|
|
m_iIMLength = 0; //Length of the preedit string.
|
|
|
|
m_iIMSelectionBegin = 0; //Index of the start of the selection in preedit string.
|
|
|
|
m_iIMSelectionLength = 0; //Length of the selection in preedit string.
|
|
|
|
|
|
|
|
m_bCursorOn = false; //Cursor state
|
|
|
|
m_iCursorTimer = 0; //Timer that iverts the cursor state
|
|
|
|
m_iDragTimer = 0; //Timer for drag selection updates
|
|
|
|
m_iLastCursorXPosition = KVI_INPUT_MARGIN; //Calculated in paintEvent
|
|
|
|
m_iSelectionAnchorChar = -1; //Character clicked at the beginning of the selection process
|
|
|
|
m_iCurHistoryIdx = -1; //No data in the history
|
|
|
|
m_bUpdatesEnabled = true;
|
|
|
|
m_pKviWindow = wnd;
|
|
|
|
m_pUserListView = view;
|
|
|
|
m_pHistory = new KviPointerList<TQString>;
|
|
|
|
m_pHistory->setAutoDelete(true);
|
|
|
|
m_bReadOnly = FALSE;
|
|
|
|
|
|
|
|
setInputMethodEnabled(true);
|
|
|
|
|
|
|
|
setBackgroundMode(TQt::NoBackground);
|
|
|
|
setFocusPolicy(TQ_StrongFocus);
|
|
|
|
setAcceptDrops(true);
|
|
|
|
setFrameStyle( LineEditPanel );
|
|
|
|
setFrameShadow( Plain );
|
|
|
|
|
|
|
|
m_pIconMenu = new KviTalPopupMenu();
|
|
|
|
connect(m_pIconMenu,TQT_SIGNAL(activated(int)),this,TQT_SLOT(iconPopupActivated(int)));
|
|
|
|
|
|
|
|
setCursor(IbeamCursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
KviInputEditor::~KviInputEditor()
|
|
|
|
{
|
|
|
|
if(g_pLastFontMetrics) delete g_pLastFontMetrics;
|
|
|
|
g_pLastFontMetrics = 0;
|
|
|
|
if(m_pIconMenu)delete m_pIconMenu;
|
|
|
|
delete m_pHistory;
|
|
|
|
if(m_iCursorTimer)killTimer(m_iCursorTimer);
|
|
|
|
killDragTimer();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::recalcFontMetrics(TQFontMetrics * pFm)
|
|
|
|
{
|
|
|
|
TQFontMetrics fm(KVI_OPTION_FONT(KviOption_fontInput));
|
|
|
|
unsigned short i;
|
|
|
|
for(i=1;i<32;i++)
|
|
|
|
{
|
|
|
|
TQChar c = getSubstituteChar(i);
|
|
|
|
g_iInputFontCharWidth[i] = fm.width(c);
|
|
|
|
if(c != TQChar(i))g_iInputFontCharWidth[i] += 4;
|
|
|
|
}
|
|
|
|
for(i=32;i<256;i++)
|
|
|
|
{
|
|
|
|
g_iInputFontCharWidth[i] = fm.width(TQChar(i));
|
|
|
|
}
|
|
|
|
g_bInputFontMetricsDirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::applyOptions()
|
|
|
|
{
|
|
|
|
g_bInputFontMetricsDirty = true;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::dragEnterEvent(TQDragEnterEvent *e)
|
|
|
|
{
|
|
|
|
if(KviUriDrag::canDecode(e))
|
|
|
|
{
|
|
|
|
e->accept(true);
|
|
|
|
// FIXME: #warning "FIX THIS COMMENTED STUFF"
|
|
|
|
/*
|
|
|
|
m_pKviWindow->m_pFrm->m_pStatusBar->tempText(__tr("Drop the file to /PARSE it"),5000);
|
|
|
|
*/
|
|
|
|
} else e->accept(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::dropEvent(TQDropEvent *e)
|
|
|
|
{
|
|
|
|
TQStringList list;
|
|
|
|
if(KviUriDrag::decodeLocalFiles(e,list))
|
|
|
|
{
|
|
|
|
//tqDebug("Local files decoded");
|
|
|
|
if(!list.isEmpty())
|
|
|
|
{
|
|
|
|
//tqDebug("List not empty");
|
|
|
|
TQStringList::ConstIterator it = list.begin(); //kewl ! :)
|
|
|
|
for( ; it != list.end(); ++it )
|
|
|
|
{
|
|
|
|
TQString tmp = *it; //wow :)
|
|
|
|
#ifndef COMPILE_ON_WINDOWS
|
|
|
|
if(tmp.length() > 0)
|
|
|
|
{
|
|
|
|
if(tmp[0] != TQChar('/'))tmp.prepend("/"); //HACK HACK HACK for TQt bug (?!?)
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
tmp.prepend("/PARSE \"");
|
|
|
|
tmp.append("\"");
|
|
|
|
if(m_pKviWindow)
|
|
|
|
KviKvsScript::run(tmp,m_pKviWindow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int KviInputEditor::heightHint() const
|
|
|
|
{
|
|
|
|
return sizeHint().height();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQSize KviInputEditor::sizeHint() const
|
|
|
|
{
|
|
|
|
//grabbed from qlineedit.cpp
|
|
|
|
constPolish();
|
|
|
|
TQFontMetrics fm(KVI_OPTION_FONT(KviOption_fontInput));
|
|
|
|
int h = TQMAX(fm.lineSpacing(), 14) + 2*2; /* innerMargin */
|
|
|
|
int w = fm.width( 'x' ) * 17; // "some"
|
|
|
|
int m = frameWidth() * 2;
|
|
|
|
return (style().tqsizeFromContents(TQStyle::CT_LineEdit, this,
|
|
|
|
TQSize( w + m, h + m ).
|
|
|
|
expandedTo(TQApplication::globalStrut())));
|
|
|
|
}
|
|
|
|
|
|
|
|
#define KVI_INPUT_DEF_BACK 100
|
|
|
|
#define KVI_INPUT_DEF_FORE 101
|
|
|
|
|
|
|
|
|
|
|
|
void KviInputEditor::drawContents(TQPainter *p)
|
|
|
|
{
|
|
|
|
if(!isVisible())return;
|
|
|
|
|
|
|
|
TQRect rect = contentsRect();
|
|
|
|
int widgetWidth = rect.width();
|
|
|
|
int widgetHeight = rect.height();
|
|
|
|
|
|
|
|
KviDoubleBuffer doublebuffer(widgetWidth,widgetHeight);
|
|
|
|
TQPixmap * pDoubleBufferPixmap = doublebuffer.pixmap();
|
|
|
|
|
|
|
|
TQPainter pa(pDoubleBufferPixmap);
|
|
|
|
SET_ANTI_ALIASING(pa);
|
|
|
|
|
|
|
|
pa.setFont(KVI_OPTION_FONT(KviOption_fontInput));
|
|
|
|
|
|
|
|
TQFontMetrics fm(pa.fontMetrics());
|
|
|
|
|
|
|
|
if(!g_pLastFontMetrics)
|
|
|
|
g_pLastFontMetrics = new TQFontMetrics(pa.fontMetrics());
|
|
|
|
|
|
|
|
if(g_bInputFontMetricsDirty)
|
|
|
|
recalcFontMetrics(&fm);
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef COMPILE_PSEUDO_TRANSPARENCY
|
|
|
|
if(g_pShadedChildGlobalDesktopBackground)
|
|
|
|
{
|
|
|
|
TQPoint pnt = mapToGlobal(rect.topLeft());
|
|
|
|
pa.drawTiledPixmap(0,0,widgetWidth,widgetHeight,*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y());
|
|
|
|
} else {
|
|
|
|
#endif
|
|
|
|
TQPixmap *pix=KVI_OPTION_PIXMAP(KviOption_pixmapInputBackground).pixmap();
|
|
|
|
|
|
|
|
pa.fillRect(0,0,widgetWidth,widgetHeight,KVI_OPTION_COLOR(KviOption_colorInputBackground));
|
|
|
|
if(pix)
|
|
|
|
KviPixmapUtils::drawPixmapWithPainter(&pa,pix,KVI_OPTION_UINT(KviOption_uintInputPixmapAlign),rect,widgetWidth,widgetHeight);
|
|
|
|
#ifdef COMPILE_PSEUDO_TRANSPARENCY
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
int curXPos = KVI_INPUT_MARGIN;
|
|
|
|
int maxXPos = widgetWidth-2*KVI_INPUT_MARGIN;
|
|
|
|
m_iCurBack = KVI_INPUT_DEF_BACK; //transparent
|
|
|
|
m_iCurFore = KVI_INPUT_DEF_FORE; //normal fore color
|
|
|
|
m_bCurBold = false;
|
|
|
|
m_bCurUnderline = false;
|
|
|
|
|
|
|
|
int bottom = widgetHeight-(widgetHeight-fm.height())/2;
|
|
|
|
int textBaseline = fm.ascent()+(widgetHeight-fm.height())/2;
|
|
|
|
int top = (widgetHeight-fm.height())/2;
|
|
|
|
|
|
|
|
runUpToTheFirstVisibleChar();
|
|
|
|
|
|
|
|
int charIdx = m_iFirstVisibleChar;
|
|
|
|
|
|
|
|
pa.setClipRect(0,0,widgetWidth,widgetHeight);
|
|
|
|
|
|
|
|
//Control the selection state
|
|
|
|
if((m_iSelectionEnd < m_iSelectionBegin) || (m_iSelectionEnd == -1) || (m_iSelectionBegin == -1))
|
|
|
|
{
|
|
|
|
m_iSelectionEnd = -1;
|
|
|
|
m_iSelectionBegin = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((m_iSelectionBegin != -1) && (m_iSelectionEnd >= m_iFirstVisibleChar))
|
|
|
|
{
|
|
|
|
int iSelStart = m_iSelectionBegin;
|
|
|
|
|
|
|
|
// TODO Refactor: write a function to combine this with the code determining iIMStart and iIMSelectionStart
|
|
|
|
if(iSelStart < m_iFirstVisibleChar)iSelStart = m_iFirstVisibleChar;
|
|
|
|
int xLeft = xPositionFromCharIndex(fm,iSelStart,TRUE);
|
|
|
|
int xRight = xPositionFromCharIndex(fm,m_iSelectionEnd + 1,TRUE);
|
|
|
|
|
|
|
|
// pa.setRasterOp(TQt::NotROP);
|
|
|
|
pa.fillRect(xLeft,frameWidth(),xRight - xLeft,widgetWidth,KVI_OPTION_COLOR(KviOption_colorInputSelectionBackground));
|
|
|
|
// pa.setRasterOp(TQt::CopyROP);
|
|
|
|
}
|
|
|
|
|
|
|
|
// When m_bIMComposing is true, the text between m_iIMStart and m_iIMStart+m_iIMLength should be highlighted to show that this is the active
|
|
|
|
// preedit area for the input method, and the text outside cannot be edited while
|
|
|
|
// composing. Maybe this can be implemented similarly as painting the selection?
|
|
|
|
// Also notice that inside the preedit, there can also be a selection, given by
|
|
|
|
// m_iSelectionBegin and m_iSelectionLength, and the widget needs to highlight that
|
|
|
|
// while in IM composition mode
|
|
|
|
if(m_bIMComposing && m_iIMLength > 0)
|
|
|
|
{
|
|
|
|
// TODO Write a function to combine IM selection drawing code. maybe the preedit area too.
|
|
|
|
int iIMSelectionStart = m_iIMSelectionBegin;
|
|
|
|
if(iIMSelectionStart < m_iFirstVisibleChar) iIMSelectionStart = m_iFirstVisibleChar;
|
|
|
|
int xIMSelectionLeft = xPositionFromCharIndex(fm,iIMSelectionStart,TRUE);
|
|
|
|
int xIMSelectionRight = xPositionFromCharIndex(fm,iIMSelectionStart + m_iIMSelectionLength,TRUE);
|
|
|
|
// pa.setRasterOp(TQt::NotROP);
|
|
|
|
pa.fillRect(xIMSelectionLeft,0,xIMSelectionRight - xIMSelectionLeft, widgetWidth,KVI_OPTION_COLOR(KviOption_colorInputSelectionBackground));
|
|
|
|
// pa.setRasterOp(TQt::CopyROP);
|
|
|
|
|
|
|
|
// highlight the IM selection
|
|
|
|
int iIMStart = m_iIMStart;
|
|
|
|
if(m_iIMStart < m_iFirstVisibleChar) m_iIMStart = m_iFirstVisibleChar;
|
|
|
|
int xIMLeft = xPositionFromCharIndex(fm,iIMStart,TRUE);
|
|
|
|
int xIMRight = xPositionFromCharIndex(fm,iIMStart + m_iIMLength,TRUE);
|
|
|
|
|
|
|
|
// underline the IM preedit
|
|
|
|
// Maybe should be put in drawTextBlock, similar to drawing underlined text
|
|
|
|
pa.drawLine(xIMLeft, bottom, xIMRight, bottom);
|
|
|
|
}
|
|
|
|
|
|
|
|
pa.setClipping(false);
|
|
|
|
|
|
|
|
while((charIdx < ((int)(m_szTextBuffer.length()))) && (curXPos < maxXPos))
|
|
|
|
{
|
|
|
|
extractNextBlock(charIdx,fm,curXPos,maxXPos);
|
|
|
|
|
|
|
|
if(m_bControlBlock)
|
|
|
|
{
|
|
|
|
pa.setPen(KVI_OPTION_COLOR(KviOption_colorInputControl));
|
|
|
|
|
|
|
|
TQString s = getSubstituteChar(m_szTextBuffer[charIdx].unicode());
|
|
|
|
|
|
|
|
// the block width is 4 pixels more than the actual character
|
|
|
|
|
|
|
|
pa.drawText(curXPos + 2,textBaseline,s,1);
|
|
|
|
|
|
|
|
pa.drawRect(curXPos,top,m_iBlockWidth-1,bottom);
|
|
|
|
} else {
|
|
|
|
if(m_iSelectionBegin!=-1)
|
|
|
|
{
|
|
|
|
int iBlockEnd=charIdx+m_iBlockLen;
|
|
|
|
//block is selected (maybe partially)
|
|
|
|
if( iBlockEnd>m_iSelectionBegin && charIdx<=m_iSelectionEnd )
|
|
|
|
{
|
|
|
|
int iSubStart,iSubLen;
|
|
|
|
//in common it consists of 3 parts: unselected-selected-unselected
|
|
|
|
//some of thst parts can be empty (for example block is fully selected)
|
|
|
|
|
|
|
|
//first part start is always equal to the block start
|
|
|
|
iSubStart=charIdx;
|
|
|
|
iSubLen = m_iSelectionBegin>charIdx ? m_iSelectionBegin-charIdx : 0;
|
|
|
|
|
|
|
|
|
|
|
|
if(iSubLen)
|
|
|
|
{
|
|
|
|
drawTextBlock(&pa,fm,curXPos,textBaseline,iSubStart,iSubLen,FALSE);
|
|
|
|
curXPos += m_iBlockWidth;
|
|
|
|
m_iBlockWidth=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//second one
|
|
|
|
iSubStart+=iSubLen;
|
|
|
|
iSubLen=m_iSelectionEnd<iBlockEnd ? m_iSelectionEnd-iSubStart+1 : iBlockEnd-iSubStart;
|
|
|
|
|
|
|
|
|
|
|
|
if(iSubLen)
|
|
|
|
{
|
|
|
|
drawTextBlock(&pa,fm,curXPos,textBaseline,iSubStart,iSubLen,TRUE);
|
|
|
|
curXPos += m_iBlockWidth;
|
|
|
|
m_iBlockWidth=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m_iSelectionEnd<(iBlockEnd-1))
|
|
|
|
{
|
|
|
|
iSubStart+=iSubLen;
|
|
|
|
iSubLen=iBlockEnd-iSubStart;
|
|
|
|
drawTextBlock(&pa,fm,curXPos,textBaseline,iSubStart,iSubLen,FALSE);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
drawTextBlock(&pa,fm,curXPos,textBaseline,charIdx,m_iBlockLen);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
drawTextBlock(&pa,fm,curXPos,textBaseline,charIdx,m_iBlockLen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
curXPos += m_iBlockWidth;
|
|
|
|
charIdx += m_iBlockLen;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Now the cursor
|
|
|
|
|
|
|
|
m_iLastCursorXPosition = KVI_INPUT_MARGIN;
|
|
|
|
m_iBlockLen = m_iFirstVisibleChar;
|
|
|
|
|
|
|
|
while(m_iBlockLen < m_iCursorPosition)
|
|
|
|
{
|
|
|
|
TQChar c = m_szTextBuffer.at(m_iBlockLen);
|
|
|
|
m_iLastCursorXPosition+= (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : fm.width(c);
|
|
|
|
m_iBlockLen++;
|
|
|
|
}
|
|
|
|
|
|
|
|
//m_iLastCursorXPosition = cur1XPos;
|
|
|
|
|
|
|
|
if(m_bCursorOn)
|
|
|
|
{
|
|
|
|
pa.setPen(KVI_OPTION_COLOR(KviOption_colorInputCursor));
|
|
|
|
pa.drawLine(m_iLastCursorXPosition,0,m_iLastCursorXPosition,widgetHeight);
|
|
|
|
} else {
|
|
|
|
pa.setPen(KVI_OPTION_COLOR(KviOption_colorInputForeground));
|
|
|
|
}
|
|
|
|
|
|
|
|
p->drawPixmap(rect.x(),rect.y(),*pDoubleBufferPixmap,0,0,widgetWidth,widgetHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::drawTextBlock(TQPainter * pa,TQFontMetrics & fm,int curXPos,int textBaseline,int charIdx,int len,bool bSelected)
|
|
|
|
{
|
|
|
|
TQString tmp = m_szTextBuffer.mid(charIdx,len);
|
|
|
|
m_iBlockWidth = fm.width(tmp);
|
|
|
|
|
|
|
|
TQRect rect = contentsRect();
|
|
|
|
int widgetHeight = rect.height();
|
|
|
|
|
|
|
|
if(m_iCurFore == KVI_INPUT_DEF_FORE)
|
|
|
|
{
|
|
|
|
pa->setPen( bSelected ? KVI_OPTION_COLOR(KviOption_colorInputSelectionForeground) : KVI_OPTION_COLOR(KviOption_colorInputForeground));
|
|
|
|
} else {
|
|
|
|
if(((unsigned char)m_iCurFore) > 16)
|
|
|
|
{
|
|
|
|
pa->setPen(KVI_OPTION_COLOR(KviOption_colorInputBackground));
|
|
|
|
} else {
|
|
|
|
pa->setPen(KVI_OPTION_MIRCCOLOR((unsigned char)m_iCurFore));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_iCurBack != KVI_INPUT_DEF_BACK)
|
|
|
|
{
|
|
|
|
if(((unsigned char)m_iCurBack) > 16)
|
|
|
|
{
|
|
|
|
pa->fillRect(curXPos,(widgetHeight-fm.height())/2,m_iBlockWidth,fm.height(),KVI_OPTION_COLOR(KviOption_colorInputForeground));
|
|
|
|
} else {
|
|
|
|
pa->fillRect(curXPos,(widgetHeight-fm.height())/2,m_iBlockWidth,fm.height(),KVI_OPTION_MIRCCOLOR((unsigned char)m_iCurBack));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pa->drawText(curXPos,textBaseline,tmp);
|
|
|
|
|
|
|
|
if(m_bCurBold)pa->drawText(curXPos+1,textBaseline,tmp);
|
|
|
|
if(m_bCurUnderline)
|
|
|
|
{
|
|
|
|
pa->drawLine(curXPos,textBaseline + fm.descent(),curXPos+m_iBlockWidth,textBaseline + fm.descent());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
TQChar KviInputEditor::getSubstituteChar(unsigned short control_code)
|
|
|
|
{
|
|
|
|
switch(control_code)
|
|
|
|
{
|
|
|
|
case KVI_TEXT_COLOR:
|
|
|
|
return TQChar('K');
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_BOLD:
|
|
|
|
return TQChar('B');
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_RESET:
|
|
|
|
return TQChar('O');
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_REVERSE:
|
|
|
|
return TQChar('R');
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_UNDERLINE:
|
|
|
|
return TQChar('U');
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_CRYPTESCAPE:
|
|
|
|
return TQChar('P');
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_ICON:
|
|
|
|
return TQChar('I');
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return TQChar(control_code);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::extractNextBlock(int idx,TQFontMetrics & fm,int curXPos,int maxXPos)
|
|
|
|
{
|
|
|
|
m_iBlockLen = 0;
|
|
|
|
m_iBlockWidth = 0;
|
|
|
|
|
|
|
|
TQChar c = m_szTextBuffer[idx];
|
|
|
|
|
|
|
|
if((c.unicode() > 32) ||
|
|
|
|
((c != TQChar(KVI_TEXT_COLOR)) &&
|
|
|
|
(c != TQChar(KVI_TEXT_BOLD)) && (c != TQChar(KVI_TEXT_UNDERLINE)) &&
|
|
|
|
(c != TQChar(KVI_TEXT_RESET)) && (c != TQChar(KVI_TEXT_REVERSE)) &&
|
|
|
|
(c != TQChar(KVI_TEXT_CRYPTESCAPE)) && (c != TQChar(KVI_TEXT_ICON))))
|
|
|
|
{
|
|
|
|
m_bControlBlock = false;
|
|
|
|
//Not a control code...run..
|
|
|
|
while((idx < ((int)(m_szTextBuffer.length()))) && (curXPos < maxXPos))
|
|
|
|
{
|
|
|
|
c = m_szTextBuffer[idx];
|
|
|
|
if((c.unicode() > 32) ||
|
|
|
|
((c != TQChar(KVI_TEXT_COLOR)) && (c != TQChar(KVI_TEXT_BOLD)) &&
|
|
|
|
(c != TQChar(KVI_TEXT_UNDERLINE)) && (c != TQChar(KVI_TEXT_RESET)) &&
|
|
|
|
(c != TQChar(KVI_TEXT_REVERSE)) && (c != TQChar(KVI_TEXT_CRYPTESCAPE)) &&
|
|
|
|
(c != TQChar(KVI_TEXT_ICON))))
|
|
|
|
{
|
|
|
|
m_iBlockLen++;
|
|
|
|
int xxx = (c.unicode() < 256 ? g_iInputFontCharWidth[c.unicode()] : fm.width(c));
|
|
|
|
m_iBlockWidth +=xxx;
|
|
|
|
curXPos +=xxx;
|
|
|
|
idx++;
|
|
|
|
} else break;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
m_bControlBlock = true;
|
|
|
|
m_iBlockLen = 1;
|
|
|
|
m_iBlockWidth = g_iInputFontCharWidth[c.unicode()];
|
|
|
|
//Control code
|
|
|
|
switch(c.unicode())
|
|
|
|
{
|
|
|
|
case KVI_TEXT_BOLD:
|
|
|
|
m_bCurBold = ! m_bCurBold;
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_UNDERLINE:
|
|
|
|
m_bCurUnderline = ! m_bCurUnderline;
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_RESET:
|
|
|
|
m_iCurFore = KVI_INPUT_DEF_FORE;
|
|
|
|
m_iCurBack = KVI_INPUT_DEF_BACK;
|
|
|
|
m_bCurBold = false;
|
|
|
|
m_bCurUnderline = false;
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_REVERSE:
|
|
|
|
{
|
|
|
|
char auxClr = m_iCurFore;
|
|
|
|
m_iCurFore = m_iCurBack;
|
|
|
|
m_iCurBack = auxClr;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_CRYPTESCAPE:
|
|
|
|
case KVI_TEXT_ICON:
|
|
|
|
// makes a single block
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_COLOR:
|
|
|
|
{
|
|
|
|
idx++;
|
|
|
|
if(idx >= ((int)(m_szTextBuffer.length())))return;
|
|
|
|
unsigned char fore;
|
|
|
|
unsigned char back;
|
|
|
|
idx = getUnicodeColorBytes(m_szTextBuffer,idx,&fore,&back);
|
|
|
|
if(fore != KVI_NOCHANGE)
|
|
|
|
{
|
|
|
|
m_iCurFore = fore;
|
|
|
|
if(back != KVI_NOCHANGE)m_iCurBack = back;
|
|
|
|
} else {
|
|
|
|
// ONLY a CTRL+K
|
|
|
|
m_iCurBack = KVI_INPUT_DEF_BACK;
|
|
|
|
m_iCurFore = KVI_INPUT_DEF_FORE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
tqDebug("Ops..");
|
|
|
|
exit(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::runUpToTheFirstVisibleChar()
|
|
|
|
{
|
|
|
|
int idx = 0;
|
|
|
|
while(idx < m_iFirstVisibleChar)
|
|
|
|
{
|
|
|
|
unsigned short c = m_szTextBuffer[idx].unicode();
|
|
|
|
if(c < 32)
|
|
|
|
{
|
|
|
|
switch(c)
|
|
|
|
{
|
|
|
|
case KVI_TEXT_BOLD:
|
|
|
|
m_bCurBold = ! m_bCurBold;
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_UNDERLINE:
|
|
|
|
m_bCurUnderline = ! m_bCurUnderline;
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_RESET:
|
|
|
|
m_iCurFore = KVI_INPUT_DEF_FORE;
|
|
|
|
m_iCurBack = KVI_INPUT_DEF_BACK;
|
|
|
|
m_bCurBold = false;
|
|
|
|
m_bCurUnderline = false;
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_REVERSE:
|
|
|
|
{
|
|
|
|
char auxClr = m_iCurFore;
|
|
|
|
m_iCurFore = m_iCurBack;
|
|
|
|
m_iCurBack = auxClr;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case KVI_TEXT_COLOR:
|
|
|
|
{
|
|
|
|
idx++;
|
|
|
|
if(idx >= ((int)(m_szTextBuffer.length())))return;
|
|
|
|
unsigned char fore;
|
|
|
|
unsigned char back;
|
|
|
|
idx = getUnicodeColorBytes(m_szTextBuffer,idx,&fore,&back);
|
|
|
|
idx--;
|
|
|
|
if(fore != KVI_NOCHANGE)m_iCurFore = fore;
|
|
|
|
else m_iCurFore = KVI_INPUT_DEF_FORE;
|
|
|
|
if(back != KVI_NOCHANGE)m_iCurBack = back;
|
|
|
|
else m_iCurBack = KVI_INPUT_DEF_BACK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
tqDebug("KviInputEditor::Encountered invisible end of the string!");
|
|
|
|
exit(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KviInputEditor::mousePressEvent(TQMouseEvent *e)
|
|
|
|
{
|
|
|
|
if(e->button() & Qt::LeftButton)
|
|
|
|
{
|
|
|
|
m_iCursorPosition = charIndexFromXPosition(e->pos().x());
|
|
|
|
//move the cursor to
|
|
|
|
int anchorX = xPositionFromCharIndex(m_iCursorPosition);
|
|
|
|
if(anchorX > (width()-frameWidth()))m_iFirstVisibleChar++;
|
|
|
|
m_iSelectionAnchorChar = m_iCursorPosition;
|
|
|
|
selectOneChar(-1);
|
|
|
|
//grabMouse(TQCursor(crossCursor));
|
|
|
|
repaintWithCursorOn();
|
|
|
|
killDragTimer();
|
|
|
|
m_iDragTimer = startTimer(KVI_INPUT_DRAG_TIMEOUT);
|
|
|
|
|
|
|
|
} else if(e->button() & Qt::RightButton)
|
|
|
|
{
|
|
|
|
int type = g_pActiveWindow->type();
|
|
|
|
|
|
|
|
//Popup menu
|
|
|
|
g_pInputPopup->clear();
|
|
|
|
|
|
|
|
TQString szClip;
|
|
|
|
|
|
|
|
TQClipboard * c = TQApplication::clipboard();
|
|
|
|
if(c)
|
|
|
|
{
|
|
|
|
szClip = c->text(TQClipboard::Clipboard);
|
|
|
|
|
|
|
|
int occ = szClip.contains(TQChar('\n'));
|
|
|
|
|
|
|
|
if(!szClip.isEmpty())
|
|
|
|
{
|
|
|
|
if(szClip.length() > 60)
|
|
|
|
{
|
|
|
|
szClip.truncate(60);
|
|
|
|
szClip.append("...");
|
|
|
|
}
|
|
|
|
szClip.replace(TQChar('&'),"&");
|
|
|
|
szClip.replace(TQChar('<'),"<");
|
|
|
|
szClip.replace(TQChar('>'),">");
|
|
|
|
szClip.replace(TQChar('\n'),"<br>");
|
|
|
|
|
|
|
|
TQString label = "<center><b>";
|
|
|
|
label += __tr2qs("Clipboard");
|
|
|
|
label += ":</b><br>";
|
|
|
|
label += szClip;
|
|
|
|
label += "<br><b>";
|
|
|
|
|
|
|
|
TQString num;
|
|
|
|
num.setNum(occ);
|
|
|
|
|
|
|
|
label += num;
|
|
|
|
label += TQChar(' ');
|
|
|
|
label += (occ == 1) ? __tr2qs("line break") : __tr2qs("line breaks");
|
|
|
|
label += "</b></center>";
|
|
|
|
|
|
|
|
TQLabel * l = new TQLabel(label,g_pInputPopup);
|
|
|
|
l->setFrameStyle(TQFrame::Raised | TQFrame::StyledPanel);
|
|
|
|
l->setMargin(5);
|
|
|
|
// FIXME: This does NOT work under TQt 4.x (they seem to consider it as bad UI design)
|
|
|
|
g_pInputPopup->insertItem(l);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int id = g_pInputPopup->insertItem(__tr2qs("Cu&t") + ACCEL_KEY(X),this,TQT_SLOT(cut()));
|
|
|
|
g_pInputPopup->setItemEnabled(id,hasSelection());
|
|
|
|
id = g_pInputPopup->insertItem(__tr2qs("&Copy") + ACCEL_KEY(C),this,TQT_SLOT(copyToClipboard()));
|
|
|
|
g_pInputPopup->setItemEnabled(id,hasSelection());
|
|
|
|
id = g_pInputPopup->insertItem(__tr2qs("&Paste") + ACCEL_KEY(V),this,TQT_SLOT(pasteClipboardWithConfirmation()));
|
|
|
|
g_pInputPopup->setItemEnabled(id,!szClip.isEmpty() && !m_bReadOnly);
|
|
|
|
id = g_pInputPopup->insertItem(__tr2qs("Paste (Slowly)"),this,TQT_SLOT(pasteSlow()));
|
|
|
|
if ((type == KVI_WINDOW_TYPE_CHANNEL) || (type == KVI_WINDOW_TYPE_QUERY) || (type == KVI_WINDOW_TYPE_DCCCHAT))
|
|
|
|
g_pInputPopup->setItemEnabled(id,!szClip.isEmpty() && !m_bReadOnly);
|
|
|
|
else
|
|
|
|
g_pInputPopup->setItemEnabled(id,false);
|
|
|
|
id = g_pInputPopup->insertItem(__tr2qs("Paste &File") + ACCEL_KEY(F),this,TQT_SLOT(pasteFile()));
|
|
|
|
if ((type != KVI_WINDOW_TYPE_CHANNEL) && (type != KVI_WINDOW_TYPE_QUERY) && (type != KVI_WINDOW_TYPE_DCCCHAT))
|
|
|
|
g_pInputPopup->setItemEnabled(id,false);
|
|
|
|
else
|
|
|
|
g_pInputPopup->setItemEnabled(id,!m_bReadOnly);
|
|
|
|
if(m_bSpSlowFlag ==true)
|
|
|
|
{
|
|
|
|
id = g_pInputPopup->insertItem(__tr2qs("Stop Paste"),this,TQT_SLOT(stopPasteSlow())); /*G&N 2005*/
|
|
|
|
}
|
|
|
|
id = g_pInputPopup->insertItem(__tr2qs("Clear"),this,TQT_SLOT(clear()));
|
|
|
|
g_pInputPopup->setItemEnabled(id,!m_szTextBuffer.isEmpty() && !m_bReadOnly);
|
|
|
|
g_pInputPopup->insertSeparator();
|
|
|
|
id = g_pInputPopup->insertItem(__tr2qs("Select All"),this,TQT_SLOT(selectAll()));
|
|
|
|
g_pInputPopup->setItemEnabled(id,(!m_szTextBuffer.isEmpty()));
|
|
|
|
|
|
|
|
|
|
|
|
g_pInputPopup->insertSeparator();
|
|
|
|
m_pIconMenu->clear();
|
|
|
|
|
|
|
|
KviPointerHashTable<TQString,KviTextIcon> * d = g_pTextIconManager->textIconDict();
|
|
|
|
KviPointerHashTableIterator<TQString,KviTextIcon> it(*d);
|
|
|
|
TQStringList strList;
|
|
|
|
while(KviTextIcon * i = it.current())
|
|
|
|
{
|
|
|
|
strList.append(it.currentKey());
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
strList.sort();
|
|
|
|
KviTextIcon * icon;
|
|
|
|
TQPixmap *pix;
|
|
|
|
|
|
|
|
for(TQStringList::Iterator iter = strList.begin(); iter != strList.end(); ++iter)
|
|
|
|
{
|
|
|
|
icon=g_pTextIconManager->lookupTextIcon(*iter);
|
|
|
|
if(icon)
|
|
|
|
{
|
|
|
|
pix = icon->pixmap();
|
|
|
|
if(pix) m_pIconMenu->insertItem(*pix,*iter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_pInputPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_BIGGRIN)),__tr2qs("Insert Icon"),m_pIconMenu);
|
|
|
|
g_pInputPopup->popup(mapToGlobal(e->pos()));
|
|
|
|
} else {
|
|
|
|
pasteSelectionWithConfirmation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void KviInputEditor::iconPopupActivated(int id)
|
|
|
|
{
|
|
|
|
if(!m_bReadOnly)
|
|
|
|
{
|
|
|
|
TQString text = m_pIconMenu->text(id);
|
|
|
|
if(!text.isEmpty())
|
|
|
|
{
|
|
|
|
text.prepend(KVI_TEXT_ICON);
|
|
|
|
text.append(' ');
|
|
|
|
insertText(text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KviInputEditor::hasSelection()
|
|
|
|
{
|
|
|
|
return ((m_iSelectionBegin != -1)&&(m_iSelectionEnd != -1));
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::copyToClipboard()
|
|
|
|
{
|
|
|
|
if(!hasSelection())return;
|
|
|
|
TQClipboard * c = TQApplication::clipboard();
|
|
|
|
if(!c)return;
|
|
|
|
TQString szTxt = m_szTextBuffer.mid(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1);
|
|
|
|
c->setText(szTxt,TQClipboard::Clipboard);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::copyToSelection(bool bDonNotCopyToClipboard)
|
|
|
|
{
|
|
|
|
if(!hasSelection())return;
|
|
|
|
TQClipboard * c = TQApplication::clipboard();
|
|
|
|
if(!c)return;
|
|
|
|
TQString szTxt = m_szTextBuffer.mid(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1);
|
|
|
|
if(c->supportsSelection())
|
|
|
|
c->setText(szTxt,TQClipboard::Selection);
|
|
|
|
else if(!bDonNotCopyToClipboard)
|
|
|
|
c->setText(szTxt,TQClipboard::Clipboard);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KviInputEditor::moveCursorTo(int idx,bool bRepaint)
|
|
|
|
{
|
|
|
|
if(idx < 0)idx = 0;
|
|
|
|
if(idx > ((int)(m_szTextBuffer.length())))idx = m_szTextBuffer.length();
|
|
|
|
if(idx > m_iCursorPosition)
|
|
|
|
{
|
|
|
|
while(m_iCursorPosition < idx)
|
|
|
|
{
|
|
|
|
moveRightFirstVisibleCharToShowCursor();
|
|
|
|
m_iCursorPosition++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m_iCursorPosition = idx;
|
|
|
|
if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar = m_iCursorPosition;
|
|
|
|
}
|
|
|
|
if(bRepaint)repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::removeSelected()
|
|
|
|
{
|
|
|
|
if(!hasSelection())return;
|
|
|
|
m_szTextBuffer.remove(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1);
|
|
|
|
moveCursorTo(m_iSelectionBegin,false);
|
|
|
|
selectOneChar(-1);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::cut()
|
|
|
|
{
|
|
|
|
if(!hasSelection())return;
|
|
|
|
TQClipboard * c = TQApplication::clipboard();
|
|
|
|
if(!c)return;
|
|
|
|
c->setText(m_szTextBuffer.mid(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1),TQClipboard::Clipboard);
|
|
|
|
m_szTextBuffer.remove(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1);
|
|
|
|
moveCursorTo(m_iSelectionBegin,false);
|
|
|
|
selectOneChar(-1);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::insertText(const TQString &text)
|
|
|
|
{
|
|
|
|
TQString szText = text; // crop away constness
|
|
|
|
if(szText.isEmpty())return;
|
|
|
|
|
|
|
|
//szText.replaceAll('\t'," "); //Do not paste tabs
|
|
|
|
|
|
|
|
//szText.replace(TQRegExp("\t")," "); // do not paste tabs
|
|
|
|
|
|
|
|
m_bUpdatesEnabled = false;
|
|
|
|
removeSelected();
|
|
|
|
m_bUpdatesEnabled = true;
|
|
|
|
|
|
|
|
if(szText.find('\n') == -1)
|
|
|
|
{
|
|
|
|
m_szTextBuffer.insert(m_iCursorPosition,szText);
|
|
|
|
m_szTextBuffer.truncate(m_iMaxBufferSize);
|
|
|
|
moveCursorTo(m_iCursorPosition + szText.length());
|
|
|
|
} else {
|
|
|
|
//Multiline paste...do not execute commands here
|
|
|
|
TQString szBlock;
|
|
|
|
while(!szText.isEmpty())
|
|
|
|
{
|
|
|
|
int idx = szText.find('\n');
|
|
|
|
if(idx != -1)
|
|
|
|
{
|
|
|
|
szBlock = szText.left(idx);
|
|
|
|
//else szBlock = TQChar(KVI_TEXT_RESET);
|
|
|
|
szText.remove(0,idx+1);
|
|
|
|
} else {
|
|
|
|
szBlock = szText;
|
|
|
|
szText = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
m_szTextBuffer.insert(m_iCursorPosition,szBlock);
|
|
|
|
m_szTextBuffer.truncate(m_iMaxBufferSize);
|
|
|
|
|
|
|
|
int pos = 0;
|
|
|
|
while((pos < ((int)(m_szTextBuffer.length()))) && (m_szTextBuffer[pos] < 33))pos++;
|
|
|
|
if((pos < ((int)(m_szTextBuffer.length()))) && (m_szTextBuffer[pos] == TQChar('/')))m_szTextBuffer.insert(pos,"\\");
|
|
|
|
|
|
|
|
returnPressed(idx != -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace (length) characters in the buffer from (start) with (text), returns
|
|
|
|
// the length of the text inserted (different from text.length() only if the
|
|
|
|
// buffer was truncated.
|
|
|
|
int KviInputEditor::replaceSegment(int start, int length, const TQString &text)
|
|
|
|
{
|
|
|
|
m_szTextBuffer.remove(start, length);
|
|
|
|
m_szTextBuffer.insert(start, text);
|
|
|
|
m_szTextBuffer.truncate(m_iMaxBufferSize);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
|
|
|
|
int iInsertedLength = text.length();
|
|
|
|
int iMaxInsertedLength = m_iMaxBufferSize - start;
|
|
|
|
if(iInsertedLength > iMaxInsertedLength) return iMaxInsertedLength;
|
|
|
|
return iInsertedLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::pasteClipboardWithConfirmation()
|
|
|
|
{
|
|
|
|
TQClipboard * c = TQApplication::clipboard();
|
|
|
|
if(!c)return;
|
|
|
|
TQString szText = c->text(TQClipboard::Clipboard);
|
|
|
|
|
|
|
|
if(szText.contains(TQChar('\n')) > 0)
|
|
|
|
{
|
|
|
|
if(m_pInputParent->inherits("KviInput"))
|
|
|
|
((KviInput*)(m_pInputParent))->multiLinePaste(szText);
|
|
|
|
} else {
|
|
|
|
insertText(szText);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::pasteSelectionWithConfirmation()
|
|
|
|
{
|
|
|
|
TQClipboard * c = TQApplication::clipboard();
|
|
|
|
if(!c)return;
|
|
|
|
TQString szText = c->text(c->supportsSelection() ? TQClipboard::Selection : TQClipboard::Clipboard);
|
|
|
|
|
|
|
|
if(szText.contains(TQChar('\n')) > 0)
|
|
|
|
{
|
|
|
|
if(m_pInputParent->inherits("KviInput"))
|
|
|
|
((KviInput*)(m_pInputParent))->multiLinePaste(szText);
|
|
|
|
} else {
|
|
|
|
insertText(szText);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::pasteSlow()
|
|
|
|
{
|
|
|
|
KviKvsScript::run("spaste.clipboard",g_pActiveWindow);
|
|
|
|
m_bSpSlowFlag = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::stopPasteSlow()
|
|
|
|
{
|
|
|
|
KviKvsScript::run("spaste.stop",g_pActiveWindow);
|
|
|
|
m_bSpSlowFlag = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::pasteFile()
|
|
|
|
{
|
|
|
|
TQString stmp = TQFileDialog::getOpenFileName("","",this,"Paste File", "Choose a file" );
|
|
|
|
if(stmp!="")
|
|
|
|
{
|
|
|
|
TQString stmp1 = "spaste.file " + stmp ;
|
|
|
|
KviKvsScript::run(stmp1,g_pActiveWindow);
|
|
|
|
m_bSpSlowFlag = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::selectAll()
|
|
|
|
{
|
|
|
|
if(m_szTextBuffer.length() > 0)
|
|
|
|
{
|
|
|
|
m_iSelectionBegin = 0;
|
|
|
|
m_iSelectionEnd = m_szTextBuffer.length()-1;
|
|
|
|
}
|
|
|
|
end();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::clear()
|
|
|
|
{
|
|
|
|
m_szTextBuffer = "";
|
|
|
|
selectOneChar(-1);
|
|
|
|
home();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::setText(const TQString text)
|
|
|
|
{
|
|
|
|
m_szTextBuffer = text;
|
|
|
|
m_szTextBuffer.truncate(m_iMaxBufferSize);
|
|
|
|
selectOneChar(-1);
|
|
|
|
end();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::mouseReleaseEvent(TQMouseEvent *)
|
|
|
|
{
|
|
|
|
if(m_iDragTimer)
|
|
|
|
{
|
|
|
|
m_iSelectionAnchorChar =-1;
|
|
|
|
//releaseMouse();
|
|
|
|
killDragTimer();
|
|
|
|
}
|
|
|
|
if(hasSelection())
|
|
|
|
copyToSelection();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::killDragTimer()
|
|
|
|
{
|
|
|
|
if(m_iDragTimer)
|
|
|
|
{
|
|
|
|
killTimer(m_iDragTimer);
|
|
|
|
m_iDragTimer = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::timerEvent(TQTimerEvent *e)
|
|
|
|
{
|
|
|
|
if(e->timerId() == m_iCursorTimer)
|
|
|
|
{
|
|
|
|
if(!hasFocus() || !isVisibleToTLW())
|
|
|
|
{
|
|
|
|
killTimer(m_iCursorTimer);
|
|
|
|
m_iCursorTimer = 0;
|
|
|
|
m_bCursorOn = false;
|
|
|
|
} else m_bCursorOn = ! m_bCursorOn;
|
|
|
|
update();
|
|
|
|
} else {
|
|
|
|
//Drag timer
|
|
|
|
handleDragSelection();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::handleDragSelection()
|
|
|
|
{
|
|
|
|
if(m_iSelectionAnchorChar == -1)return;
|
|
|
|
|
|
|
|
TQPoint pnt = mapFromGlobal(TQCursor::pos());
|
|
|
|
|
|
|
|
|
|
|
|
if(pnt.x() <= 0)
|
|
|
|
{
|
|
|
|
//Left side dragging
|
|
|
|
if(m_iFirstVisibleChar > 0)m_iFirstVisibleChar--;
|
|
|
|
m_iCursorPosition = m_iFirstVisibleChar;
|
|
|
|
} else if(pnt.x() >= width())
|
|
|
|
{
|
|
|
|
//Right side dragging...add a single character to the selection on the right
|
|
|
|
if(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
|
|
|
|
{
|
|
|
|
moveRightFirstVisibleCharToShowCursor();
|
|
|
|
m_iCursorPosition++;
|
|
|
|
} //else at the end of the selection...don't move anything
|
|
|
|
} else {
|
|
|
|
//Inside the window...
|
|
|
|
m_iCursorPosition = charIndexFromXPosition(pnt.x());
|
|
|
|
}
|
|
|
|
if(m_iCursorPosition == m_iSelectionAnchorChar)selectOneChar(-1);
|
|
|
|
else {
|
|
|
|
if(m_iCursorPosition > m_iSelectionAnchorChar)
|
|
|
|
{
|
|
|
|
m_iSelectionBegin = m_iSelectionAnchorChar;
|
|
|
|
m_iSelectionEnd = m_iCursorPosition-1;
|
|
|
|
} else {
|
|
|
|
m_iSelectionBegin = m_iCursorPosition;
|
|
|
|
m_iSelectionEnd = m_iSelectionAnchorChar-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::returnPressed(bool bRepaint)
|
|
|
|
{
|
|
|
|
if (!m_szTextBuffer.isEmpty() /* && (!m_pHistory->current() || m_szTextBuffer.compare(*(m_pHistory->current())))*/)
|
|
|
|
{
|
|
|
|
if(m_pInputParent->inherits("KviInput"))
|
|
|
|
g_pInputHistory->add(new TQString(m_szTextBuffer));
|
|
|
|
|
|
|
|
m_pHistory->insert(0,new TQString(m_szTextBuffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
__range_valid(KVI_INPUT_MAX_LOCAL_HISTORY_ENTRIES > 1); //ABSOLUTELY NEEDED, if not, pHist will be destroyed...
|
|
|
|
if(m_pHistory->count() > KVI_INPUT_MAX_LOCAL_HISTORY_ENTRIES)m_pHistory->removeLast();
|
|
|
|
|
|
|
|
m_iCurHistoryIdx = -1;
|
|
|
|
|
|
|
|
// FIXME: ALL THIS STUFF SHOULD BE CONVERTED TO TQString
|
|
|
|
/*
|
|
|
|
if(m_pInputParent->inherits("KviInput"))
|
|
|
|
{
|
|
|
|
TQString szBuffer(m_szTextBuffer);
|
|
|
|
m_szTextBuffer="";
|
|
|
|
selectOneChar(-1);
|
|
|
|
m_iCursorPosition = 0;
|
|
|
|
m_iFirstVisibleChar = 0;
|
|
|
|
if(bRepaint)repaintWithCursorOn();
|
|
|
|
KviUserInput::parse(szBuffer,m_pKviWindow);
|
|
|
|
} else {
|
|
|
|
*/
|
|
|
|
emit enterPressed();
|
|
|
|
/*
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::focusInEvent(TQFocusEvent *)
|
|
|
|
{
|
|
|
|
if(m_iCursorTimer==0)
|
|
|
|
{
|
|
|
|
m_iCursorTimer = startTimer(KVI_INPUT_BLINK_TIME);
|
|
|
|
m_bCursorOn = true;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
// XIM handling...
|
|
|
|
setMicroFocusHint(1,1,width() - 2,height() - 2,true,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::focusOutEvent(TQFocusEvent *)
|
|
|
|
{
|
|
|
|
if(m_iCursorTimer)killTimer(m_iCursorTimer);
|
|
|
|
m_iCursorTimer = 0;
|
|
|
|
m_bCursorOn = false;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KviInputEditor::internalCursorRight(bool bShift)
|
|
|
|
{
|
|
|
|
if(m_iCursorPosition >= ((int)(m_szTextBuffer.length())))return;
|
|
|
|
moveRightFirstVisibleCharToShowCursor();
|
|
|
|
//Grow the selection if needed
|
|
|
|
if(bShift)
|
|
|
|
{
|
|
|
|
if((m_iSelectionBegin > -1)&&(m_iSelectionEnd > -1))
|
|
|
|
{
|
|
|
|
if(m_iSelectionEnd == m_iCursorPosition-1)m_iSelectionEnd++;
|
|
|
|
else if(m_iSelectionBegin == m_iCursorPosition)m_iSelectionBegin++;
|
|
|
|
else selectOneChar(m_iCursorPosition);
|
|
|
|
} else selectOneChar(m_iCursorPosition);
|
|
|
|
} else selectOneChar(-1);
|
|
|
|
m_iCursorPosition++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::internalCursorLeft(bool bShift)
|
|
|
|
{
|
|
|
|
if(m_iCursorPosition <= 0)return;
|
|
|
|
|
|
|
|
if(bShift)
|
|
|
|
{
|
|
|
|
if((m_iSelectionBegin > -1)&&(m_iSelectionEnd > -1))
|
|
|
|
{
|
|
|
|
if(m_iSelectionBegin == m_iCursorPosition)m_iSelectionBegin--;
|
|
|
|
else if(m_iSelectionEnd == m_iCursorPosition-1)m_iSelectionEnd--;
|
|
|
|
else selectOneChar(m_iCursorPosition - 1);
|
|
|
|
} else selectOneChar(m_iCursorPosition - 1);
|
|
|
|
} else selectOneChar(-1);
|
|
|
|
|
|
|
|
m_iCursorPosition--;
|
|
|
|
if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar--;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remember the text before and after the cursor at this point, and put them
|
|
|
|
// before and after the text inserted by IM in imEndEvent.
|
|
|
|
// hagabaka
|
|
|
|
void KviInputEditor::imStartEvent(TQIMEvent *e)
|
|
|
|
{
|
|
|
|
removeSelected();
|
|
|
|
m_iIMStart = m_iIMSelectionBegin = m_iCursorPosition;
|
|
|
|
m_iIMLength = 0;
|
|
|
|
m_bIMComposing = true;
|
|
|
|
e->accept();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Whenever the IM's preedit changes, update the visuals and internal data. refer to <http://doc.trolltech.com/3.3/qimevent.html> */
|
|
|
|
// hagabaka
|
|
|
|
void KviInputEditor::imComposeEvent(TQIMEvent *e)
|
|
|
|
{
|
|
|
|
// replace the old pre-edit string with e->text()
|
|
|
|
m_bUpdatesEnabled = false;
|
|
|
|
m_iIMLength = replaceSegment(m_iIMStart, m_iIMLength, e->text());
|
|
|
|
|
|
|
|
// update selection inside the pre-edit
|
|
|
|
m_iIMSelectionBegin = m_iIMStart + e->cursorPos();
|
|
|
|
m_iIMSelectionLength = e->selectionLength();
|
|
|
|
moveCursorTo(m_iIMSelectionBegin);
|
|
|
|
|
|
|
|
|
|
|
|
// repaint
|
|
|
|
m_bUpdatesEnabled = true;
|
|
|
|
repaintWithCursorOn();
|
|
|
|
e->accept();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Input method is done; put its resulting text to where the preedit area was
|
|
|
|
// hagabaka
|
|
|
|
void KviInputEditor::imEndEvent(TQIMEvent *e)
|
|
|
|
{
|
|
|
|
// replace the preedit area with the IM result text
|
|
|
|
m_bUpdatesEnabled = false;
|
|
|
|
m_iIMLength = replaceSegment(m_iIMStart, m_iIMLength, e->text());
|
|
|
|
|
|
|
|
// move cursor to after the IM result text
|
|
|
|
moveCursorTo(m_iIMStart + m_iIMLength);
|
|
|
|
|
|
|
|
// repaint
|
|
|
|
m_bUpdatesEnabled = true;
|
|
|
|
repaintWithCursorOn();
|
|
|
|
|
|
|
|
// reset data
|
|
|
|
m_bIMComposing = false;
|
|
|
|
e->accept();
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME According to <http://www.kde.gr.jp/~asaki/how-to-support-input-method.html>, if the XIM
|
|
|
|
// style used is OverTheTop, code needs to be added in keyPressEvent handler */
|
|
|
|
// hagabaka
|
|
|
|
void KviInputEditor::keyPressEvent(TQKeyEvent *e)
|
|
|
|
{
|
|
|
|
// disable the keyPress handling when IM is in composition.
|
|
|
|
if(m_bIMComposing)
|
|
|
|
{
|
|
|
|
e->ignore();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// completion thingies
|
|
|
|
|
|
|
|
if(!m_bReadOnly)
|
|
|
|
{
|
|
|
|
if((e->key() == TQt::Key_Tab) || (e->key() == TQt::Key_BackTab))
|
|
|
|
{
|
|
|
|
completion(e->state() & TQt::ShiftButton);
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
m_bLastCompletionFinished=1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(e->key() == TQt::Key_Escape)
|
|
|
|
{
|
|
|
|
emit escapePressed();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((e->state() & TQt::AltButton) || (e->state() & TQt::ControlButton))
|
|
|
|
{
|
|
|
|
switch(e->key())
|
|
|
|
{
|
|
|
|
case TQt::Key_Backspace:
|
|
|
|
if(m_pInputParent->inherits("KviInput"))
|
|
|
|
{
|
|
|
|
((KviInput*)(m_pInputParent))->multiLinePaste(m_szTextBuffer);
|
|
|
|
clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Make CtrlKey and CommandKey ("Apple") behave equally on MacOSX.
|
|
|
|
//This way typical X11 and Apple shortcuts can be used simultanously within the input line.
|
|
|
|
#ifndef Q_OS_MACX
|
|
|
|
if(e->state() & TQt::ControlButton)
|
|
|
|
#else
|
|
|
|
if((e->state() & TQt::ControlButton) || (e->state() & TQt::MetaButton))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
switch(e->key())
|
|
|
|
{
|
|
|
|
case TQt::Key_Right:
|
|
|
|
if(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
|
|
|
|
{
|
|
|
|
// skip whitespace
|
|
|
|
while(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
|
|
|
|
{
|
|
|
|
if(!m_szTextBuffer.at(m_iCursorPosition).isSpace())break;
|
|
|
|
internalCursorRight(e->state() & TQt::ShiftButton);
|
|
|
|
}
|
|
|
|
// skip nonwhitespace
|
|
|
|
while(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
|
|
|
|
{
|
|
|
|
if(m_szTextBuffer.at(m_iCursorPosition).isSpace())break;
|
|
|
|
internalCursorRight(e->state() & TQt::ShiftButton);
|
|
|
|
}
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_Left:
|
|
|
|
if(m_iCursorPosition > 0)
|
|
|
|
{
|
|
|
|
// skip whitespace
|
|
|
|
while(m_iCursorPosition > 0)
|
|
|
|
{
|
|
|
|
if(!m_szTextBuffer.at(m_iCursorPosition - 1).isSpace())break;
|
|
|
|
internalCursorLeft(e->state() & TQt::ShiftButton);
|
|
|
|
}
|
|
|
|
// skip nonwhitespace
|
|
|
|
while(m_iCursorPosition > 0)
|
|
|
|
{
|
|
|
|
if(m_szTextBuffer.at(m_iCursorPosition - 1).isSpace())break;
|
|
|
|
internalCursorLeft(e->state() & TQt::ShiftButton);
|
|
|
|
}
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_K:
|
|
|
|
{
|
|
|
|
if(!m_bReadOnly)
|
|
|
|
{
|
|
|
|
insertChar(KVI_TEXT_COLOR);
|
|
|
|
int xPos = xPositionFromCharIndex(m_iCursorPosition);
|
|
|
|
if(xPos > 24)xPos-=24;
|
|
|
|
if(!g_pColorWindow)g_pColorWindow = new KviColorWindow();
|
|
|
|
if(xPos+g_pColorWindow->width() > width())xPos = width()-(g_pColorWindow->width()+2);
|
|
|
|
g_pColorWindow->move(mapToGlobal(TQPoint(xPos,-35)));
|
|
|
|
g_pColorWindow->popup(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_B:
|
|
|
|
if(!m_bReadOnly) insertChar(KVI_TEXT_BOLD);
|
|
|
|
break;
|
|
|
|
case TQt::Key_O:
|
|
|
|
if(!m_bReadOnly) insertChar(KVI_TEXT_RESET);
|
|
|
|
break;
|
|
|
|
case TQt::Key_U:
|
|
|
|
if(!m_bReadOnly) insertChar(KVI_TEXT_UNDERLINE);
|
|
|
|
break;
|
|
|
|
case TQt::Key_R:
|
|
|
|
if(!m_bReadOnly) insertChar(KVI_TEXT_REVERSE);
|
|
|
|
break;
|
|
|
|
case TQt::Key_P:
|
|
|
|
if(!m_bReadOnly) insertChar(KVI_TEXT_CRYPTESCAPE); // DO NOT CRYPT THIS STUFF
|
|
|
|
break;
|
|
|
|
case TQt::Key_I:
|
|
|
|
{
|
|
|
|
if(!m_bReadOnly)
|
|
|
|
{
|
|
|
|
insertChar(KVI_TEXT_ICON); // THE NEXT WORD IS AN ICON NAME
|
|
|
|
int xPos = xPositionFromCharIndex(m_iCursorPosition);
|
|
|
|
if(xPos > 24)xPos-=24;
|
|
|
|
if(!g_pTextIconWindow)g_pTextIconWindow = new KviTextIconWindow();
|
|
|
|
if(xPos+g_pTextIconWindow->width() > width())xPos = width()-(g_pTextIconWindow->width()+2);
|
|
|
|
g_pTextIconWindow->move(mapToGlobal(TQPoint(xPos,-KVI_TEXTICON_WIN_HEIGHT)));
|
|
|
|
g_pTextIconWindow->popup(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_C:
|
|
|
|
copyToClipboard();
|
|
|
|
break;
|
|
|
|
case TQt::Key_X:
|
|
|
|
if(!m_bReadOnly) cut();
|
|
|
|
break;
|
|
|
|
case TQt::Key_V:
|
|
|
|
if(!m_bReadOnly) pasteClipboardWithConfirmation();
|
|
|
|
break;
|
|
|
|
//case TQt::Key_Backspace:
|
|
|
|
case TQt::Key_W:
|
|
|
|
if(m_iCursorPosition > 0 && !m_bReadOnly && !hasSelection())
|
|
|
|
{
|
|
|
|
// skip whitespace
|
|
|
|
while(m_iCursorPosition > 0)
|
|
|
|
{
|
|
|
|
if(!m_szTextBuffer.at(m_iCursorPosition - 1).isSpace())break;
|
|
|
|
m_szTextBuffer.remove(m_iCursorPosition-1,1);
|
|
|
|
m_iCursorPosition--;
|
|
|
|
if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar--;
|
|
|
|
}
|
|
|
|
// skip nonwhitespace
|
|
|
|
while(m_iCursorPosition > 0)
|
|
|
|
{
|
|
|
|
if(m_szTextBuffer.at(m_iCursorPosition - 1).isSpace())break;
|
|
|
|
m_szTextBuffer.remove(m_iCursorPosition-1,1);
|
|
|
|
m_iCursorPosition--;
|
|
|
|
if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar--;
|
|
|
|
}
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_PageUp:
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolDisableInputHistory)) break;
|
|
|
|
if(m_pInputParent->inherits("KviInput"))
|
|
|
|
((KviInput*)(m_pInputParent))->historyButtonClicked();
|
|
|
|
break;
|
|
|
|
case TQt::Key_F:
|
|
|
|
if(m_pKviWindow)
|
|
|
|
if(m_pKviWindow->view())m_pKviWindow->view()->toggleToolWidget();
|
|
|
|
break;
|
|
|
|
case TQt::Key_A:
|
|
|
|
m_iSelectionBegin=0;
|
|
|
|
m_iSelectionEnd=m_szTextBuffer.length()-1;
|
|
|
|
m_iCursorPosition=m_szTextBuffer.length();
|
|
|
|
repaintWithCursorOn();
|
|
|
|
break;
|
|
|
|
case TQt::Key_Return:
|
|
|
|
case TQt::Key_Enter:
|
|
|
|
if(m_pInputParent->inherits("KviInput"))
|
|
|
|
{
|
|
|
|
TQString szBuffer(m_szTextBuffer);
|
|
|
|
m_szTextBuffer="";
|
|
|
|
selectOneChar(-1);
|
|
|
|
m_iCursorPosition = 0;
|
|
|
|
m_iFirstVisibleChar = 0;
|
|
|
|
repaintWithCursorOn();
|
|
|
|
KviUserInput::parseNonCommand(szBuffer,m_pKviWindow);
|
|
|
|
if (!szBuffer.isEmpty())
|
|
|
|
{
|
|
|
|
g_pInputHistory->add(new TQString(szBuffer));
|
|
|
|
m_pHistory->insert(0,new TQString(szBuffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
__range_valid(KVI_INPUT_MAX_LOCAL_HISTORY_ENTRIES > 1); //ABSOLUTELY NEEDED, if not, pHist will be destroyed...
|
|
|
|
if(m_pHistory->count() > KVI_INPUT_MAX_LOCAL_HISTORY_ENTRIES)m_pHistory->removeLast();
|
|
|
|
|
|
|
|
m_iCurHistoryIdx = -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if(!m_bReadOnly) insertText(e->text());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((e->state() & TQt::AltButton) && (e->state() & TQt::Keypad))
|
|
|
|
{
|
|
|
|
// TQt::Key_Meta seems to substitute TQt::Key_Alt on some keyboards
|
|
|
|
if((e->key() == TQt::Key_Alt) || (e->key() == TQt::Key_Meta))
|
|
|
|
{
|
|
|
|
m_szAltKeyCode = "";
|
|
|
|
return;
|
|
|
|
} else if((e->ascii() >= '0') && (e->ascii() <= '9'))
|
|
|
|
{
|
|
|
|
m_szAltKeyCode += e->ascii();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//tqDebug("%c",e->ascii());
|
|
|
|
if(!m_bReadOnly) {
|
|
|
|
insertText(e->text());
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(e->state() & TQt::ShiftButton)
|
|
|
|
{
|
|
|
|
switch(e->key())
|
|
|
|
{
|
|
|
|
case TQt::Key_Insert:
|
|
|
|
if(!m_bReadOnly) pasteClipboardWithConfirmation();
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
case TQt::Key_PageUp:
|
|
|
|
if(m_pKviWindow)
|
|
|
|
if(m_pKviWindow->view())m_pKviWindow->view()->prevLine();
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
case TQt::Key_PageDown:
|
|
|
|
if(m_pKviWindow)
|
|
|
|
if(m_pKviWindow->view())m_pKviWindow->view()->nextLine();
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(e->key())
|
|
|
|
{
|
|
|
|
case TQt::Key_Right:
|
|
|
|
if(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
|
|
|
|
{
|
|
|
|
internalCursorRight(e->state() & TQt::ShiftButton);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_Left:
|
|
|
|
if(m_iCursorPosition > 0)
|
|
|
|
{
|
|
|
|
internalCursorLeft(e->state() & TQt::ShiftButton);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_Backspace:
|
|
|
|
if(!m_bReadOnly)
|
|
|
|
{
|
|
|
|
if(hasSelection() && (m_iSelectionEnd >= m_iCursorPosition-1) && (m_iSelectionBegin <= m_iCursorPosition))
|
|
|
|
{
|
|
|
|
//remove the selection
|
|
|
|
m_szTextBuffer.remove(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1);
|
|
|
|
m_iCursorPosition = m_iSelectionBegin;
|
|
|
|
if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar = m_iCursorPosition;
|
|
|
|
} else if(m_iCursorPosition > 0) {
|
|
|
|
m_iCursorPosition--;
|
|
|
|
m_szTextBuffer.remove(m_iCursorPosition,1);
|
|
|
|
if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar--;
|
|
|
|
}
|
|
|
|
selectOneChar(-1);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_Delete:
|
|
|
|
if(!m_bReadOnly)
|
|
|
|
{
|
|
|
|
if(hasSelection()) removeSelected();
|
|
|
|
else if(m_iCursorPosition < (int)m_szTextBuffer.length())
|
|
|
|
{
|
|
|
|
m_szTextBuffer.remove(m_iCursorPosition,1);
|
|
|
|
selectOneChar(-1);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_Home:
|
|
|
|
if(m_iCursorPosition > 0)
|
|
|
|
{
|
|
|
|
if(e->state() & TQt::ShiftButton)
|
|
|
|
{
|
|
|
|
if((m_iSelectionBegin == -1)&&(m_iSelectionEnd == -1))m_iSelectionEnd = m_iCursorPosition - 1;
|
|
|
|
m_iSelectionBegin = 0;
|
|
|
|
} else {
|
|
|
|
selectOneChar(-1);
|
|
|
|
}
|
|
|
|
home();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_End://we should call it even the cursor is at the end for deselecting
|
|
|
|
if(e->state() & TQt::ShiftButton)
|
|
|
|
{
|
|
|
|
if((m_iSelectionBegin == -1)&&(m_iSelectionEnd == -1))m_iSelectionBegin = m_iCursorPosition;
|
|
|
|
m_iSelectionEnd = m_szTextBuffer.length()-1;
|
|
|
|
} else {
|
|
|
|
selectOneChar(-1);
|
|
|
|
}
|
|
|
|
end();
|
|
|
|
break;
|
|
|
|
case TQt::Key_Up:
|
|
|
|
if(!m_bReadOnly)
|
|
|
|
{
|
|
|
|
if(m_pHistory->count() > 0)
|
|
|
|
{
|
|
|
|
if(m_iCurHistoryIdx < 0)
|
|
|
|
{
|
|
|
|
m_szSaveTextBuffer = m_szTextBuffer;
|
|
|
|
m_szTextBuffer = *(m_pHistory->at(0));
|
|
|
|
m_iCurHistoryIdx = 0;
|
|
|
|
} else if(m_iCurHistoryIdx >= (int)(m_pHistory->count()-1))
|
|
|
|
{
|
|
|
|
m_szTextBuffer=m_szSaveTextBuffer;
|
|
|
|
m_iCurHistoryIdx = -1;
|
|
|
|
} else {
|
|
|
|
m_iCurHistoryIdx++;
|
|
|
|
m_szTextBuffer = *(m_pHistory->at(m_iCurHistoryIdx));
|
|
|
|
}
|
|
|
|
selectOneChar(-1);
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolInputHistoryCursorAtEnd))end();
|
|
|
|
else home();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_Down:
|
|
|
|
if(!m_bReadOnly)
|
|
|
|
{
|
|
|
|
if(m_pHistory->count() > 0)
|
|
|
|
{
|
|
|
|
if(m_iCurHistoryIdx < 0)
|
|
|
|
{
|
|
|
|
m_szSaveTextBuffer = m_szTextBuffer;
|
|
|
|
m_szTextBuffer = *(m_pHistory->at(m_pHistory->count()-1));
|
|
|
|
m_iCurHistoryIdx =m_pHistory->count()-1;
|
|
|
|
} else if(m_iCurHistoryIdx == 0)
|
|
|
|
{
|
|
|
|
m_szTextBuffer=m_szSaveTextBuffer;
|
|
|
|
m_iCurHistoryIdx = -1;
|
|
|
|
} else {
|
|
|
|
m_iCurHistoryIdx--;
|
|
|
|
m_szTextBuffer = *(m_pHistory->at(m_iCurHistoryIdx));
|
|
|
|
}
|
|
|
|
selectOneChar(-1);
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolInputHistoryCursorAtEnd))end();
|
|
|
|
else home();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_PageUp:
|
|
|
|
if(m_pKviWindow)
|
|
|
|
if(m_pKviWindow->view())m_pKviWindow->view()->prevPage();
|
|
|
|
break;
|
|
|
|
case TQt::Key_PageDown:
|
|
|
|
if(m_pKviWindow)
|
|
|
|
if(m_pKviWindow->view())m_pKviWindow->view()->nextPage();
|
|
|
|
break;
|
|
|
|
case TQt::Key_Return:
|
|
|
|
case TQt::Key_Enter:
|
|
|
|
returnPressed();
|
|
|
|
break;
|
|
|
|
case TQt::Key_Alt:
|
|
|
|
case TQt::Key_Meta:
|
|
|
|
m_szAltKeyCode = "";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if(!e->text().isEmpty() && !m_bReadOnly)
|
|
|
|
insertText(e->text());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::keyReleaseEvent(TQKeyEvent *e)
|
|
|
|
{
|
|
|
|
if((e->key() == TQt::Key_Alt) || (e->key() == TQt::Key_Meta))
|
|
|
|
{
|
|
|
|
if(m_szAltKeyCode.hasData())
|
|
|
|
{
|
|
|
|
bool bOk;
|
|
|
|
unsigned short ch = m_szAltKeyCode.toUShort(&bOk);
|
|
|
|
if(bOk && ch != 0)
|
|
|
|
{
|
|
|
|
//tqDebug("INSERTING CHAR %d",ch);
|
|
|
|
insertChar(TQChar(ch));
|
|
|
|
e->accept();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_szAltKeyCode = "";
|
|
|
|
}
|
|
|
|
e->ignore();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::getWordBeforeCursor(TQString &buffer,bool * bIsFirstWordInLine)
|
|
|
|
{
|
|
|
|
if(m_szTextBuffer.isEmpty() || m_iCursorPosition <= 0)
|
|
|
|
{
|
|
|
|
buffer = "";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer = m_szTextBuffer.left(m_iCursorPosition);
|
|
|
|
|
|
|
|
int idx = buffer.findRev(' ');
|
|
|
|
int idx2 = buffer.findRev(','); // This is for comma separated lists...
|
|
|
|
int idx3 = buffer.findRev('(');
|
|
|
|
int idx4 = buffer.findRev('"');
|
|
|
|
if(idx2 > idx)idx = idx2;
|
|
|
|
if(idx3 > idx)idx = idx3;
|
|
|
|
if(idx4 > idx)idx = idx4;
|
|
|
|
*bIsFirstWordInLine = false;
|
|
|
|
if(idx > -1)buffer.remove(0,idx+1);
|
|
|
|
else *bIsFirstWordInLine = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::completion(bool bShift)
|
|
|
|
{
|
|
|
|
// FIXME: Spaces in directory completion can mess everything completely
|
|
|
|
// On windows the KVI_PATH_SEPARATOR_CHARacters are breaking everything...
|
|
|
|
// Well.... :D
|
|
|
|
|
|
|
|
TQString word;
|
|
|
|
TQString match;
|
|
|
|
|
|
|
|
bool bFirstWordInLine;
|
|
|
|
getWordBeforeCursor(word,&bFirstWordInLine);
|
|
|
|
if(word.isEmpty())
|
|
|
|
{
|
|
|
|
if(m_szLastCompletedNick.isEmpty())return; // nothing to complete
|
|
|
|
else {
|
|
|
|
// this is standard nick completion continued
|
|
|
|
standardNickCompletion(bShift,word,bFirstWordInLine);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
KviPointerList<TQString> tmp;
|
|
|
|
tmp.setAutoDelete(true);
|
|
|
|
|
|
|
|
bool bIsCommand = false;
|
|
|
|
bool bIsDir = false;
|
|
|
|
bool bIsNick = false;
|
|
|
|
|
|
|
|
unsigned short uc = word[0].unicode();
|
|
|
|
|
|
|
|
if(uc == '/')
|
|
|
|
{
|
|
|
|
if(bFirstWordInLine)
|
|
|
|
{
|
|
|
|
// command completion
|
|
|
|
word.remove(0,1);
|
|
|
|
if(word.isEmpty())return;
|
|
|
|
KviKvsKernel::instance()->completeCommand(word,&tmp);
|
|
|
|
bIsCommand = true;
|
|
|
|
} else {
|
|
|
|
// directory completion attempt
|
|
|
|
g_pApp->completeDirectory(word,&tmp);
|
|
|
|
bIsDir = true;
|
|
|
|
}
|
|
|
|
} else if(uc == '$')
|
|
|
|
{
|
|
|
|
// function/identifer completion
|
|
|
|
word.remove(0,1);
|
|
|
|
if(word.isEmpty())return;
|
|
|
|
KviKvsKernel::instance()->completeFunction(word,&tmp);
|
|
|
|
} else if(uc == '#' || uc == '&' || uc == '!')
|
|
|
|
{
|
|
|
|
if(m_pKviWindow)
|
|
|
|
{
|
|
|
|
if( (word.length()==1) && (m_pKviWindow->windowName()[0].unicode()==uc))
|
|
|
|
{
|
|
|
|
match=m_pKviWindow->windowName();
|
|
|
|
match.append(" ");
|
|
|
|
replaceWordBeforeCursor(word,match,false);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
if(m_pKviWindow->console())
|
|
|
|
m_pKviWindow->console()->completeChannel(word,&tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME: Complete also on irc:// starting strings, not only irc.?
|
|
|
|
} else if(KviTQString::equalCIN(word,"irc.",4))
|
|
|
|
{
|
|
|
|
// irc server name
|
|
|
|
if(m_pKviWindow)
|
|
|
|
if(m_pKviWindow->console())
|
|
|
|
m_pKviWindow->console()->completeServer(word,&tmp);
|
|
|
|
} else {
|
|
|
|
// empty word will end up here
|
|
|
|
if(m_pUserListView)
|
|
|
|
{
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolBashLikeNickCompletion))
|
|
|
|
{
|
|
|
|
m_pUserListView->completeNickBashLike(word,&tmp,bShift);
|
|
|
|
bIsNick = true;
|
|
|
|
} else {
|
|
|
|
standardNickCompletion(bShift,word,bFirstWordInLine);
|
|
|
|
repaintWithCursorOn();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lookup the longest exact match
|
|
|
|
|
|
|
|
if(tmp.count() > 0)
|
|
|
|
{
|
|
|
|
if(tmp.count() == 1)
|
|
|
|
{
|
|
|
|
match = *(tmp.first());
|
|
|
|
if(bIsCommand)match.append(' ');
|
|
|
|
else if(bIsNick)
|
|
|
|
{
|
|
|
|
if(!KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix).isEmpty())
|
|
|
|
{
|
|
|
|
if(bFirstWordInLine || (!KVI_OPTION_BOOL(KviOption_boolUseNickCompletionPostfixForFirstWordOnly)))
|
|
|
|
match.append(KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
TQString all;
|
|
|
|
TQString * s = tmp.first();
|
|
|
|
match = *s;
|
|
|
|
int wLen = word.length();
|
|
|
|
for(;s;s = tmp.next())
|
|
|
|
{
|
|
|
|
if(s->length() < match.length())
|
|
|
|
match.remove(s->length(),match.length() - s->length());
|
|
|
|
// All the matches here have length >= word.len()!!!
|
|
|
|
const TQChar * b1 = KviTQString::nullTerminatedArray(*s) + wLen;
|
|
|
|
const TQChar * b2 = KviTQString::nullTerminatedArray(match) + wLen;
|
|
|
|
const TQChar * c1 = b1;
|
|
|
|
const TQChar * c2 = b2;
|
|
|
|
if(bIsDir)while(c1->unicode() && (c1->unicode() == c2->unicode()))c1++,c2++;
|
|
|
|
else while(c1->unicode() && (c1->lower().unicode() == c2->lower().unicode()))c1++,c2++;
|
|
|
|
int len = wLen + (c1 - b1);
|
|
|
|
if(len < ((int)(match.length())))match.remove(len,match.length() - len);
|
|
|
|
if(!all.isEmpty())all.append(", ");
|
|
|
|
all.append(*s);
|
|
|
|
}
|
|
|
|
if(m_pKviWindow)
|
|
|
|
m_pKviWindow->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("%d matches: %Q"),tmp.count(),&all);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if(m_pKviWindow)
|
|
|
|
m_pKviWindow->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("No matches"));
|
|
|
|
|
|
|
|
if(!match.isEmpty())
|
|
|
|
{
|
|
|
|
//if(!bIsDir && !bIsNick)match = match.lower(); <-- why? It is nice to have
|
|
|
|
// $module.someFunctionName instad
|
|
|
|
// of unreadable $module.somefunctionfame
|
|
|
|
replaceWordBeforeCursor(word,match,false);
|
|
|
|
}
|
|
|
|
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::replaceWordBeforeCursor(const TQString &word,const TQString &replacement,bool bRepaint)
|
|
|
|
{
|
|
|
|
selectOneChar(-1);
|
|
|
|
m_iCursorPosition -= word.length();
|
|
|
|
m_szTextBuffer.remove(m_iCursorPosition,word.length());
|
|
|
|
m_szTextBuffer.insert(m_iCursorPosition,replacement);
|
|
|
|
m_szTextBuffer.truncate(m_iMaxBufferSize);
|
|
|
|
moveCursorTo(m_iCursorPosition + replacement.length());
|
|
|
|
if(bRepaint)repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::standardNickCompletion(bool bAddMask,TQString &word,bool bFirstWordInLine)
|
|
|
|
{
|
|
|
|
// FIXME: this could be really simplified...
|
|
|
|
if(!m_pUserListView)return;
|
|
|
|
selectOneChar(-1);
|
|
|
|
|
|
|
|
TQString buffer;
|
|
|
|
if(m_szLastCompletedNick.isEmpty())
|
|
|
|
{
|
|
|
|
// New completion session: we NEED sth to complete
|
|
|
|
if(word.isEmpty())return;
|
|
|
|
if(m_pUserListView->completeNickStandard(word,m_szLastCompletedNick,buffer,bAddMask))
|
|
|
|
{
|
|
|
|
// completed: save the buffer
|
|
|
|
m_szLastCompletionBuffer = m_szTextBuffer;
|
|
|
|
m_iLastCompletionCursorPosition = m_iCursorPosition;
|
|
|
|
m_iLastCompletionCursorXPosition = m_iLastCursorXPosition;
|
|
|
|
m_iLastCompletionFirstVisibleChar = m_iFirstVisibleChar;
|
|
|
|
m_szLastCompletedNick = buffer;
|
|
|
|
if(!KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix).isEmpty())
|
|
|
|
{
|
|
|
|
if(bFirstWordInLine || (!KVI_OPTION_BOOL(KviOption_boolUseNickCompletionPostfixForFirstWordOnly)))
|
|
|
|
buffer.append(KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix));
|
|
|
|
}
|
|
|
|
replaceWordBeforeCursor(word,buffer,false);
|
|
|
|
m_bLastCompletionFinished=0;
|
|
|
|
// REPAINT CALLED FROM OUTSIDE!
|
|
|
|
} // else no match at all
|
|
|
|
} else if(!m_bLastCompletionFinished) {
|
|
|
|
// Old session
|
|
|
|
// swap the buffers
|
|
|
|
m_szTextBuffer = m_szLastCompletionBuffer;
|
|
|
|
m_iCursorPosition = m_iLastCompletionCursorPosition;
|
|
|
|
m_iLastCursorXPosition = m_iLastCompletionCursorXPosition;
|
|
|
|
m_iFirstVisibleChar = m_iLastCompletionFirstVisibleChar;
|
|
|
|
// re-extract
|
|
|
|
//word = m_szTextBuffer.left(m_iCursorPosition);
|
|
|
|
|
|
|
|
getWordBeforeCursor(word,&bFirstWordInLine);
|
|
|
|
if(word.isEmpty())return;
|
|
|
|
if(m_pUserListView->completeNickStandard(word,m_szLastCompletedNick,buffer,bAddMask))
|
|
|
|
{
|
|
|
|
// completed
|
|
|
|
m_szLastCompletedNick = buffer;
|
|
|
|
if(!KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix).isEmpty())
|
|
|
|
{
|
|
|
|
if(bFirstWordInLine || (!KVI_OPTION_BOOL(KviOption_boolUseNickCompletionPostfixForFirstWordOnly)))
|
|
|
|
buffer.append(KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix));
|
|
|
|
}
|
|
|
|
replaceWordBeforeCursor(word,buffer,false);
|
|
|
|
m_bLastCompletionFinished=0;
|
|
|
|
// REPAINT CALLED FROM OUTSIDE!
|
|
|
|
} else {
|
|
|
|
m_bLastCompletionFinished=1;
|
|
|
|
m_szLastCompletedNick = "";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Old session finished
|
|
|
|
// re-extract
|
|
|
|
//word = m_szTextBuffer.left(m_iCursorPosition);
|
|
|
|
//getWordBeforeCursor(word,&bFirstWordInLine);
|
|
|
|
if(word.isEmpty())return;
|
|
|
|
if(m_pUserListView->completeNickStandard(word,"",buffer,bAddMask))
|
|
|
|
{
|
|
|
|
// completed
|
|
|
|
m_szLastCompletionBuffer = m_szTextBuffer;
|
|
|
|
m_iLastCompletionCursorPosition = m_iCursorPosition;
|
|
|
|
m_iLastCompletionCursorXPosition = m_iLastCursorXPosition;
|
|
|
|
m_iLastCompletionFirstVisibleChar = m_iFirstVisibleChar;
|
|
|
|
m_szLastCompletedNick = buffer;
|
|
|
|
if(!KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix).isEmpty())
|
|
|
|
{
|
|
|
|
if(bFirstWordInLine || (!KVI_OPTION_BOOL(KviOption_boolUseNickCompletionPostfixForFirstWordOnly)))
|
|
|
|
buffer.append(KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix));
|
|
|
|
}
|
|
|
|
replaceWordBeforeCursor(word,buffer,false);
|
|
|
|
m_bLastCompletionFinished=0;
|
|
|
|
// REPAINT CALLED FROM OUTSIDE!
|
|
|
|
} else {
|
|
|
|
m_bLastCompletionFinished=1;
|
|
|
|
m_szLastCompletedNick = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Funky helpers
|
|
|
|
|
|
|
|
void KviInputEditor::end()
|
|
|
|
{
|
|
|
|
m_iLastCursorXPosition = frameWidth();
|
|
|
|
m_iCursorPosition = 0;
|
|
|
|
m_iFirstVisibleChar = 0;
|
|
|
|
while(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
|
|
|
|
{
|
|
|
|
moveRightFirstVisibleCharToShowCursor();
|
|
|
|
m_iCursorPosition++;
|
|
|
|
}
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::home()
|
|
|
|
{
|
|
|
|
m_iFirstVisibleChar = 0;
|
|
|
|
m_iCursorPosition = 0;
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::insertChar(TQChar c)
|
|
|
|
{
|
|
|
|
if(m_szTextBuffer.length() >= m_iMaxBufferSize)return;
|
|
|
|
|
|
|
|
// Kill the selection
|
|
|
|
if((m_iSelectionBegin > -1) || (m_iSelectionEnd > -1))
|
|
|
|
{
|
|
|
|
if((m_iCursorPosition >= m_iSelectionBegin) && (m_iCursorPosition <= m_iSelectionEnd))
|
|
|
|
{
|
|
|
|
m_bUpdatesEnabled = false;
|
|
|
|
removeSelected();
|
|
|
|
m_bUpdatesEnabled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
selectOneChar(-1);
|
|
|
|
m_szTextBuffer.insert(m_iCursorPosition,c);
|
|
|
|
moveRightFirstVisibleCharToShowCursor();
|
|
|
|
m_iCursorPosition++;
|
|
|
|
repaintWithCursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::moveRightFirstVisibleCharToShowCursor()
|
|
|
|
{
|
|
|
|
// :)
|
|
|
|
TQFontMetrics fm(KVI_OPTION_FONT(KviOption_fontInput));
|
|
|
|
|
|
|
|
TQChar c = m_szTextBuffer.at(m_iCursorPosition);
|
|
|
|
|
|
|
|
m_iLastCursorXPosition += (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : fm.width(c);
|
|
|
|
while(m_iLastCursorXPosition >= contentsRect().width()-2*KVI_INPUT_MARGIN)
|
|
|
|
{
|
|
|
|
c = m_szTextBuffer.at(m_iFirstVisibleChar);
|
|
|
|
m_iLastCursorXPosition -= (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : fm.width(c);
|
|
|
|
m_iFirstVisibleChar++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::repaintWithCursorOn()
|
|
|
|
{
|
|
|
|
// :)
|
|
|
|
if(m_bUpdatesEnabled)
|
|
|
|
{
|
|
|
|
m_bCursorOn = true;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInputEditor::selectOneChar(int pos)
|
|
|
|
{
|
|
|
|
m_iSelectionBegin = pos;
|
|
|
|
m_iSelectionEnd = pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KviInputEditor::charIndexFromXPosition(int xPos)
|
|
|
|
{
|
|
|
|
int curXPos = frameWidth()+KVI_INPUT_MARGIN;
|
|
|
|
int curChar = m_iFirstVisibleChar;
|
|
|
|
int bufLen = m_szTextBuffer.length();
|
|
|
|
|
|
|
|
TQFontMetrics fm(KVI_OPTION_FONT(KviOption_fontInput));
|
|
|
|
while(curChar < bufLen)
|
|
|
|
{
|
|
|
|
TQChar c = m_szTextBuffer.at(curChar);
|
|
|
|
int widthCh = (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : fm.width(c);
|
|
|
|
if(xPos < (curXPos+(widthCh/2)))return curChar;
|
|
|
|
else if(xPos < (curXPos+widthCh))return (curChar+1);
|
|
|
|
{
|
|
|
|
curXPos+=widthCh;
|
|
|
|
curChar++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return curChar;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KviInputEditor::xPositionFromCharIndex(TQFontMetrics& fm,int chIdx,bool bContentsCoords)
|
|
|
|
{
|
|
|
|
// FIXME: this could use fm.width(m_szTextBuffer,chIdx)
|
|
|
|
int curXPos = bContentsCoords ? KVI_INPUT_MARGIN : frameWidth()+KVI_INPUT_MARGIN;
|
|
|
|
int curChar = m_iFirstVisibleChar;
|
|
|
|
while(curChar < chIdx)
|
|
|
|
{
|
|
|
|
TQChar c = m_szTextBuffer.at(curChar);
|
|
|
|
curXPos += (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : fm.width(c);
|
|
|
|
curChar++;
|
|
|
|
}
|
|
|
|
return curXPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KviInputEditor::xPositionFromCharIndex(int chIdx,bool bContentsCoords)
|
|
|
|
{
|
|
|
|
// FIXME: this could use fm.width(m_szTextBuffer,chIdx)
|
|
|
|
int curXPos = bContentsCoords ? KVI_INPUT_MARGIN : frameWidth()+KVI_INPUT_MARGIN;
|
|
|
|
int curChar = m_iFirstVisibleChar;
|
|
|
|
//tqDebug("%i",g_pLastFontMetrics);
|
|
|
|
if(!g_pLastFontMetrics) g_pLastFontMetrics = new TQFontMetrics(KVI_OPTION_FONT(KviOption_fontInput));
|
|
|
|
while(curChar < chIdx)
|
|
|
|
{
|
|
|
|
TQChar c = m_szTextBuffer.at(curChar);
|
|
|
|
curXPos += (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : g_pLastFontMetrics->width(c);
|
|
|
|
curChar++;
|
|
|
|
}
|
|
|
|
return curXPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: texticons
|
|
|
|
@type:
|
|
|
|
generic
|
|
|
|
@title:
|
|
|
|
The KVIrc TextIcons extension
|
|
|
|
@short:
|
|
|
|
The KVIrc TextIcons extension
|
|
|
|
@body:
|
|
|
|
Starting from version 3.0.0 KVIrc supports the TextIcon extension
|
|
|
|
to the standard IRC protocol. It is a mean for sending text enriched
|
|
|
|
of small images without sending the images themselves.[br]
|
|
|
|
The idea is quite simple: the IRC client (and it's user) associates
|
|
|
|
some small images to text strings (called icon tokens) and the strings are sent
|
|
|
|
in place of the images preceeded by a special escape character.[br]
|
|
|
|
The choosen escape character is 29 (hex 0x1d) which corresponds
|
|
|
|
to the ASCII group separator.[br]
|
|
|
|
So for example if a client has the association of the icon token "rose" with a small
|
|
|
|
icon containing a red rose flower then KVIrc could send the string
|
|
|
|
"<0x1d>rose" in the message stream to ask the remote parties to
|
|
|
|
display such an icon. If the remote parties don't have this association
|
|
|
|
then they will simply strip the control code and display the string "rose",
|
|
|
|
(eventually showing it in some enchanced way).[br]
|
|
|
|
The icon tokens can't contain spaces
|
|
|
|
so the receiving clients stop the extraction of the icon strings
|
|
|
|
when a space, an icon escape or the message termination is encountered.
|
|
|
|
[br]
|
|
|
|
<icon escape> := character 0x1d (ASCII group separator)[br]
|
|
|
|
<icon token> := any character with the exception of 0x1d, CR,LF and SPACE.[br]
|
|
|
|
[br]
|
|
|
|
Please note that this is a KVIrc extension and the remote clients
|
|
|
|
that don't support this feature will not display the icon (and will
|
|
|
|
eventually show the 0x1d character in the data stream).[br]
|
|
|
|
If you like this feature please either convince the remote users
|
|
|
|
to try KVIrc or tell them to write to their client developers asking
|
|
|
|
for this simple feature to be implemented.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: commandline
|
|
|
|
@title:
|
|
|
|
The Commandline Input Features
|
|
|
|
@type:
|
|
|
|
generic
|
|
|
|
@short:
|
|
|
|
Commandline input features
|
|
|
|
@body:
|
|
|
|
[big]Principles of operation[/big]
|
|
|
|
[p]
|
|
|
|
The idea is simple: anything that starts with a slash (/) character
|
|
|
|
is interpreted as a command. Anything else is plain text that is
|
|
|
|
sent to the target of the window (channel, query, dcc chat etc..).
|
|
|
|
[/p]
|
|
|
|
[big]The two operating modes[/big]
|
|
|
|
[p]
|
|
|
|
The commandline input has two operating modes: the "user friendly mode" and
|
|
|
|
the "kvs mode". In the user friendly mode all the parameters of the commands
|
|
|
|
are interpreted exactly like you type them. There is no special interpretation
|
|
|
|
of $,%,-,( and ; characters. This allows you to type "/me is happy ;)", for example.
|
|
|
|
In the kvs mode the full parameter interpretation is enabled and the commands
|
|
|
|
work just like in any other script editor. This means that anything that
|
|
|
|
starts with a $ is a function call, anything that starts with a % is a variable,
|
|
|
|
the dash characters after command names are interpreted as switches and ; is the
|
|
|
|
command separator. This in turn does NOT allow you to type "/me is happy ;)"
|
|
|
|
because ; is the command separator and ) will be interpreted as the beginning
|
|
|
|
of the next command. In KVS mode you obviously have to escape the ; character
|
|
|
|
by typing "/me is happy \;)". The user friendly mode is good for everyday chatting
|
|
|
|
and for novice users while the KVS mode is for experts that know that minimum about
|
|
|
|
scripting languages. Please note that in the user-friendly mode you're not allowed
|
|
|
|
to type multiple commands at once :).
|
|
|
|
[/p]
|
|
|
|
[big]Default Key Bindings:[/big][br]
|
|
|
|
Ctrl+B: Inserts the 'bold' mIRC text control character<br>
|
|
|
|
Ctrl+K: Inserts the 'color' mIRC text control character<br>
|
|
|
|
Ctrl+R: Inserts the 'reverse' mIRC text control character<br>
|
|
|
|
Ctrl+U: Inserts the 'underline' mIRC text control character<br>
|
|
|
|
Ctrl+O: Inserts the 'reset' mIRC text control character<br>
|
|
|
|
Ctrl+P: Inserts the 'non-crypt' (plain text) KVIrc control character used to disable encryption of the current text line<br>
|
|
|
|
Ctrl+C: Copies the selected text to clipboard<br>
|
|
|
|
Ctrl+X: Cuts the selected text<br>
|
|
|
|
Ctrl+V: Pastes the clipboard contents (same as middle mouse click)<br>
|
|
|
|
Ctrl+I: Inserts the 'icon' control code and pops up the icon list box<br>
|
|
|
|
Ctrl+A: Select all<br>
|
|
|
|
CursorUp: Moves backward in the command history<br>
|
|
|
|
CursorDown: Moves forward in the command history<br>
|
|
|
|
CursorRight: Moves the cursor to the right<br>
|
|
|
|
CursorLeft: Moves the cursor to the left :)<br>
|
|
|
|
Shift+CursorLeft: Moves the selection to the left<br>
|
|
|
|
Shift+RightCursor: Moves the selection to the right<br>
|
|
|
|
Ctrl+CursorLeft: Moves the cursor one word left<br>
|
|
|
|
Ctrl+CursorRight: Moves the cursor one word right<br>
|
|
|
|
Ctrl+Shift+CursorLeft: Moves the selection one word left<br>
|
|
|
|
Ctrl+Shift+CursorRight: Moves the selection one word right<br>
|
|
|
|
Tab: Nickname, function/command, or filename completion (see below)<br>
|
|
|
|
Shift+Tab: Hostmask or function/command completion (see below)<br>
|
|
|
|
Alt+<numeric_sequence>: Inserts the character by ASCII/Unicode code<br>
|
|
|
|
<example>
|
|
|
|
Alt+32: Inserts ASCII/Unicode character 32: ' ' (a space)
|
|
|
|
Alt+00032: Same as above :)
|
|
|
|
Alt+13: Inserts the Carriage Return (CR) control character
|
|
|
|
Alt+77: Inserts ASCII/Unicode character 77: 'M'
|
|
|
|
Alt+23566: Inserts Unicode character 23566 (an ideogram)
|
|
|
|
</example>
|
|
|
|
Also look at the <a href="shortcuts.kvihelp">global shortcuts</a> reference.<br>
|
|
|
|
If you drop a file on this widget, a <a href="parse.kvihelp">/PARSE <filename></a> will be executed.<br>
|
|
|
|
You can enable word substitution in the preferences dialog.<br>
|
|
|
|
For example, if you choose to substitute "afaik" with "As far as I know",<br>
|
|
|
|
when you will type "afaik" somewhere in the command line, and then
|
|
|
|
press Space or Return, that word will be replaced with "As far as I know".<br>
|
|
|
|
Experiment with it :)<br>
|
|
|
|
The Tab key activates the completion of the current word.<br>
|
|
|
|
If a word is prefixed with a '/', it is treated as a command to be completed,
|
|
|
|
if it begins with '$', it is treated as a function or identifier to be completed,
|
|
|
|
otherwise it is treated as a nickname or filename to be completed.<br>
|
|
|
|
<example>
|
|
|
|
/ec<Tab> will produce /echo<space>
|
|
|
|
/echo $loca<Tab> will produce /echo $localhost
|
|
|
|
</example>
|
|
|
|
Multiple matches are listed in the view window and the word is completed
|
|
|
|
to the common part of all the matches.<br>
|
|
|
|
<example>
|
|
|
|
$sel<Tab;> will find multiple matches and produce $selected
|
|
|
|
</example>
|
|
|
|
Experiment with that too :)
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KviInput::KviInput(KviWindow *par,KviUserListView * view)
|
|
|
|
: TQWidget(par,"input")
|
|
|
|
{
|
|
|
|
TQBoxLayout* pLayout=new TQHBoxLayout(this);
|
|
|
|
pLayout->setAutoAdd(true);
|
|
|
|
pLayout->setDirection(TQBoxLayout::RightToLeft);
|
|
|
|
|
|
|
|
pLayout->setMargin(0);
|
|
|
|
pLayout->setSpacing(0);
|
|
|
|
|
|
|
|
m_pWindow = par;
|
|
|
|
m_pMultiLineEditor = 0;
|
|
|
|
|
|
|
|
m_pHideToolsButton = new KviStyledToolButton(this,"hide_container_button");
|
|
|
|
|
|
|
|
m_pHideToolsButton->setUsesBigPixmap(false);
|
|
|
|
m_pHideToolsButton->setFixedWidth(10);
|
|
|
|
|
|
|
|
if(g_pIconManager->getBigIcon("kvi_horizontal_left.png"))
|
|
|
|
m_pHideToolsButton->setPixmap(*(g_pIconManager->getBigIcon("kvi_horizontal_left.png")));
|
|
|
|
|
|
|
|
connect(m_pHideToolsButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(toggleToolButtons()));
|
|
|
|
|
|
|
|
m_pButtonContainer=new KviTalHBox(this);
|
|
|
|
m_pButtonContainer->setSpacing(0);
|
|
|
|
|
|
|
|
|
|
|
|
m_pHistoryButton = new KviStyledToolButton(m_pButtonContainer,"historybutton");
|
|
|
|
m_pHistoryButton->setUsesBigPixmap(false);
|
|
|
|
//m_pHistoryButton->setUpdatesEnabled(TRUE); ???
|
|
|
|
TQIconSet is1;
|
|
|
|
if(!KVI_OPTION_BOOL(KviOption_boolDisableInputHistory))//G&N mar 2005
|
|
|
|
{
|
|
|
|
is1.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)),TQIconSet::Small);
|
|
|
|
m_pHistoryButton->setIconSet(is1);
|
|
|
|
KviTalToolTip::add(m_pHistoryButton,__tr2qs("Show History<br><Ctrl+PageUp>"));
|
|
|
|
connect(m_pHistoryButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(historyButtonClicked()));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
is1.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUITSPLIT)),TQIconSet::Small);
|
|
|
|
m_pHistoryButton->setIconSet(is1);
|
|
|
|
KviTalToolTip::add(m_pHistoryButton,__tr2qs("Input History Disabled"));
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pIconButton = new KviStyledToolButton(m_pButtonContainer,"iconbutton");
|
|
|
|
m_pIconButton->setUsesBigPixmap(false);
|
|
|
|
TQIconSet is3;
|
|
|
|
is3.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_BIGGRIN)),TQIconSet::Small);
|
|
|
|
m_pIconButton->setIconSet(is3);
|
|
|
|
KviTalToolTip::add(m_pIconButton,__tr2qs("Show Icons Popup<br><Ctrl+I><br>See also /help texticons"));
|
|
|
|
|
|
|
|
connect(m_pIconButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(iconButtonClicked()));
|
|
|
|
|
|
|
|
|
|
|
|
m_pCommandlineModeButton = new KviStyledToolButton(m_pButtonContainer,"commandlinemodebutton");
|
|
|
|
m_pCommandlineModeButton->setUsesBigPixmap(false);
|
|
|
|
m_pCommandlineModeButton->setToggleButton(true);
|
|
|
|
TQIconSet is0;
|
|
|
|
is0.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SAYSMILE)),TQIconSet::Small,TQIconSet::Normal,TQIconSet::On);
|
|
|
|
is0.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SAYKVS)),TQIconSet::Small,TQIconSet::Normal,TQIconSet::Off);
|
|
|
|
m_pCommandlineModeButton->setIconSet(is0);
|
|
|
|
KviTalToolTip::add(m_pCommandlineModeButton,__tr2qs("User friendly commandline mode<br>See also /help commandline"));
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolCommandlineInUserFriendlyModeByDefault))
|
|
|
|
m_pCommandlineModeButton->setOn(true);
|
|
|
|
|
|
|
|
|
|
|
|
m_pMultiEditorButton = new KviStyledToolButton(m_pButtonContainer,"multieditorbutton");
|
|
|
|
m_pMultiEditorButton->setToggleButton(true);
|
|
|
|
m_pMultiEditorButton->setUsesBigPixmap(false);
|
|
|
|
TQIconSet is2;
|
|
|
|
is2.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TERMINAL)),TQIconSet::Small,TQIconSet::Normal,TQIconSet::On);
|
|
|
|
is2.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TERMINAL)),TQIconSet::Small,TQIconSet::Normal,TQIconSet::Off);
|
|
|
|
m_pMultiEditorButton->setIconSet(is2);
|
|
|
|
TQString szTip = __tr2qs("Multi-line Editor<br><Alt+Backspace>");
|
|
|
|
szTip += " - <Ctrl+Backspace>";
|
|
|
|
KviTalToolTip::add(m_pMultiEditorButton,szTip);
|
|
|
|
|
|
|
|
connect(m_pMultiEditorButton,TQT_SIGNAL(toggled(bool)),this,TQT_SLOT(multilineEditorButtonToggled(bool)));
|
|
|
|
|
|
|
|
m_pInputEditor = new KviInputEditor(this,par,view);
|
|
|
|
connect(m_pInputEditor,TQT_SIGNAL(enterPressed()),this,TQT_SLOT(inputEditorEnterPressed()));
|
|
|
|
m_pInputEditor->setSizePolicy(TQSizePolicy(TQSizePolicy::Ignored,TQSizePolicy::Ignored));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pLayout->setStretchFactor(m_pInputEditor,100000);
|
|
|
|
pLayout->setStretchFactor(m_pButtonContainer,0);
|
|
|
|
pLayout->setStretchFactor(m_pHideToolsButton,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
KviInput::~KviInput()
|
|
|
|
{
|
|
|
|
if(m_pMultiLineEditor)KviScriptEditor::destroyInstance(m_pMultiLineEditor);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KviInput::isButtonsHidden()
|
|
|
|
{
|
|
|
|
return m_pButtonContainer->isHidden();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::setButtonsHidden(bool bHidden)
|
|
|
|
{
|
|
|
|
if(!m_pHideToolsButton || !m_pButtonContainer) return;
|
|
|
|
if(bHidden==m_pButtonContainer->isHidden()) return;
|
|
|
|
m_pButtonContainer->setHidden(bHidden);
|
|
|
|
TQPixmap* pix= bHidden ?
|
|
|
|
g_pIconManager->getBigIcon("kvi_horizontal_right.png") :
|
|
|
|
g_pIconManager->getBigIcon("kvi_horizontal_left.png");
|
|
|
|
if(pix)
|
|
|
|
m_pHideToolsButton->setPixmap(*pix);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::toggleToolButtons()
|
|
|
|
{
|
|
|
|
setButtonsHidden(!isButtonsHidden());
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::inputEditorEnterPressed()
|
|
|
|
{
|
|
|
|
TQString szText = m_pInputEditor->text();
|
|
|
|
KviUserInput::parse(szText,m_pWindow,TQString(),m_pCommandlineModeButton->isOn());
|
|
|
|
m_pInputEditor->setText("");
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::keyPressEvent(TQKeyEvent *e)
|
|
|
|
{
|
|
|
|
//tqDebug("KviInput::keyPressEvent(key:%d,state:%d,text:%s)",e->key(),e->state(),e->text().isEmpty() ? "empty" : e->text().utf8().data());
|
|
|
|
|
|
|
|
if((e->state() & TQt::ControlButton) || (e->state() & TQt::AltButton) || (e->state() & TQt::MetaButton))
|
|
|
|
{
|
|
|
|
switch(e->key())
|
|
|
|
{
|
|
|
|
case TQt::Key_Backspace:
|
|
|
|
//if(m_pMultiLineEditor)
|
|
|
|
multilineEditorButtonToggled(!m_pMultiLineEditor);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(e->state() & TQt::ControlButton)
|
|
|
|
{
|
|
|
|
switch(e->key())
|
|
|
|
{
|
|
|
|
case TQt::Key_Enter:
|
|
|
|
case TQt::Key_Return:
|
|
|
|
{
|
|
|
|
if(m_pMultiLineEditor)
|
|
|
|
{
|
|
|
|
TQString szText;
|
|
|
|
m_pMultiLineEditor->getText(szText);
|
|
|
|
if(szText.isEmpty())return;
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolWarnAboutPastingMultipleLines))
|
|
|
|
{
|
|
|
|
if(szText.length() > 256)
|
|
|
|
{
|
|
|
|
if(szText[0] != '/')
|
|
|
|
{
|
|
|
|
int nLines = szText.contains('\n') + 1;
|
|
|
|
if(nLines > 15)
|
|
|
|
{
|
|
|
|
int nRet = TQMessageBox::question(
|
|
|
|
this,
|
|
|
|
__tr2qs("Confirm Multiline Message"),
|
|
|
|
__tr2qs("You're about to send a message with %1 lines of text.<br><br>" \
|
|
|
|
"There is nothing wrong with it, this warning is<br>" \
|
|
|
|
"here to prevent you from accidentally sending<br>" \
|
|
|
|
"a really large message just because you didn't edit it<br>" \
|
|
|
|
"properly after pasting text from the clipboard.<br><br>" \
|
|
|
|
"Do you want the message to be sent?").arg(nLines),
|
|
|
|
__tr2qs("Yes, always"),
|
|
|
|
__tr2qs("Yes"),
|
|
|
|
__tr2qs("No"),
|
|
|
|
1,2);
|
|
|
|
switch(nRet)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
KVI_OPTION_BOOL(KviOption_boolWarnAboutPastingMultipleLines) = false;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
default: // also case 1
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
KviUserInput::parse(szText,m_pWindow,TQString(),m_pCommandlineModeButton->isOn());
|
|
|
|
m_pMultiLineEditor->setText("");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQt::Key_PageUp:
|
|
|
|
historyButtonClicked();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::multiLinePaste(const TQString &text)
|
|
|
|
{
|
|
|
|
if(!m_pMultiLineEditor)multilineEditorButtonToggled(true);
|
|
|
|
m_pMultiLineEditor->setText(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::multilineEditorButtonToggled(bool bOn)
|
|
|
|
{
|
|
|
|
if(m_pMultiLineEditor)
|
|
|
|
{
|
|
|
|
if(bOn)return;
|
|
|
|
KviScriptEditor::destroyInstance(m_pMultiLineEditor);
|
|
|
|
m_pMultiLineEditor = 0;
|
|
|
|
m_pInputEditor->show();
|
|
|
|
m_pWindow->childrenTreeChanged(0);
|
|
|
|
m_pInputEditor->setFocus();
|
|
|
|
m_pMultiEditorButton->setOn(false);
|
|
|
|
} else {
|
|
|
|
if(!bOn)return;
|
|
|
|
m_pMultiLineEditor = KviScriptEditor::createInstance(this);
|
|
|
|
TQString szText = __tr2qs("<Ctrl+Return>; submits, <Alt+Backspace>; hides this editor");
|
|
|
|
// compatibility entry to avoid breaking translation just before a release... :)
|
|
|
|
szText.replace("Alt+Backspace","Ctrl+Backspace");
|
|
|
|
m_pMultiLineEditor->setFindText(szText);
|
|
|
|
m_pMultiLineEditor->setFindLineeditReadOnly(true);
|
|
|
|
m_pInputEditor->hide();
|
|
|
|
m_pMultiLineEditor->show();
|
|
|
|
m_pWindow->childrenTreeChanged(m_pMultiLineEditor);
|
|
|
|
m_pMultiLineEditor->setFocus();
|
|
|
|
m_pMultiEditorButton->setOn(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::iconButtonClicked()
|
|
|
|
{
|
|
|
|
if(!g_pTextIconWindow)g_pTextIconWindow = new KviTextIconWindow();
|
|
|
|
TQPoint pnt = m_pIconButton->mapToGlobal(TQPoint(m_pIconButton->width(),0));
|
|
|
|
g_pTextIconWindow->move(pnt.x()-g_pTextIconWindow->width(),pnt.y() - g_pTextIconWindow->height());
|
|
|
|
g_pTextIconWindow->popup(this,true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::historyButtonClicked()
|
|
|
|
{
|
|
|
|
if(!g_pHistoryWindow)g_pHistoryWindow = new KviHistoryWindow();
|
|
|
|
|
|
|
|
TQPoint pnt = mapToGlobal(TQPoint(0,0));
|
|
|
|
|
|
|
|
g_pHistoryWindow->setGeometry(pnt.x(),pnt.y() - KVI_HISTORY_WIN_HEIGHT,width(),KVI_HISTORY_WIN_HEIGHT);
|
|
|
|
g_pHistoryWindow->popup(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define BUTTON_WIDTH 20
|
|
|
|
|
|
|
|
/*void KviInput::resizeEvent(TQResizeEvent *e)
|
|
|
|
{
|
|
|
|
//m_pButtonContainer
|
|
|
|
m_pInputEditor->setGeometry(0,0,m_pButtonContainer->isVisible() ? width() - (BUTTON_WIDTH * 4)-10 : width() - 10,height());
|
|
|
|
if(m_pMultiLineEditor)m_pMultiLineEditor->setGeometry(0,0,m_pButtonContainer->isVisible() ? width() - (BUTTON_WIDTH * 4)-10 : width() - 10,height());
|
|
|
|
if(m_pButtonContainer->isVisible()) m_pButtonContainer->setGeometry(width() - (BUTTON_WIDTH * 4)-10,0,BUTTON_WIDTH*4,height());
|
|
|
|
|
|
|
|
m_pHideToolsButton->setGeometry(width() - 10,0,10,height());
|
|
|
|
|
|
|
|
TQWidget::resizeEvent(e);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
void KviInput::setFocus()
|
|
|
|
{
|
|
|
|
// redirect setFocus() to the right children
|
|
|
|
if(m_pMultiLineEditor)m_pMultiLineEditor->setFocus();
|
|
|
|
else m_pInputEditor->setFocus();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::focusInEvent(TQFocusEvent * e)
|
|
|
|
{
|
|
|
|
// if we get a focus in event , redirect the focus to the children
|
|
|
|
if(m_pMultiLineEditor)m_pMultiLineEditor->setFocus();
|
|
|
|
else m_pInputEditor->setFocus();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int KviInput::heightHint() const
|
|
|
|
{
|
|
|
|
return m_pMultiLineEditor ? 120 : m_pInputEditor->heightHint();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::setText(const TQString &text)
|
|
|
|
{
|
|
|
|
// FIXME: Latin1 -> TQString ?
|
|
|
|
if(m_pMultiLineEditor)m_pMultiLineEditor->setText(text);
|
|
|
|
else m_pInputEditor->setText(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::insertChar(char c)
|
|
|
|
{
|
|
|
|
m_pInputEditor->insertChar(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::insertText(const TQString& text)
|
|
|
|
{
|
|
|
|
m_pInputEditor->insertText(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::applyOptions()
|
|
|
|
{
|
|
|
|
if(g_pLastFontMetrics) delete g_pLastFontMetrics;
|
|
|
|
g_pLastFontMetrics = 0;
|
|
|
|
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolDisableInputHistory))//G&N mar 2005
|
|
|
|
{
|
|
|
|
TQIconSet is1;
|
|
|
|
is1.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUITSPLIT)),TQIconSet::Small);
|
|
|
|
m_pHistoryButton->setIconSet(is1);
|
|
|
|
KviTalToolTip::add(m_pHistoryButton,__tr2qs("Input History Disabled"));
|
|
|
|
m_pHistoryButton->disconnect(TQT_SIGNAL(clicked()));
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!KVI_OPTION_BOOL(KviOption_boolDisableInputHistory))
|
|
|
|
{
|
|
|
|
TQIconSet is1;
|
|
|
|
is1.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)),TQIconSet::Small);
|
|
|
|
m_pHistoryButton->setIconSet(is1);
|
|
|
|
KviTalToolTip::add(m_pHistoryButton,__tr2qs("Show History<br><Ctrl+PageUp>"));
|
|
|
|
connect(m_pHistoryButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(historyButtonClicked()));
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pInputEditor->applyOptions();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviInput::setFocusProxy(TQWidget *)
|
|
|
|
{
|
|
|
|
/* do nothing */
|
|
|
|
}
|
|
|
|
|
|
|
|
//const TQString & KviInput::text()
|
|
|
|
TQString KviInput::text()
|
|
|
|
{
|
|
|
|
TQString szText;
|
|
|
|
if(m_pMultiLineEditor)
|
|
|
|
m_pMultiLineEditor->getText(szText);
|
|
|
|
else
|
|
|
|
szText=m_pInputEditor->text();
|
|
|
|
return szText;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kvi_input.moc"
|