Skip to content

Commit

Permalink
Numbering Post-Push
Browse files Browse the repository at this point in the history
Numbering Post-Push is a good function for discussion in one post.
See the issue pcman-bbs#42(pcman-bbs#42).

1). Add a field PostPushNum in the line structure.
The line structure:
struct{ char[ColsPerPage], char='\0', CTermCharAttr[ColsPerPage, char=0]}
[ ColsPerPage*char + '\0' + ColsPerPage*CTermCharAttr + PostPushNum ]

2). Detect Post-Push lines and numbering them whenever a character is added in the screen buffer of CTermData.

3). Save the number in PostPushNum of Post-Push lines.

4). Draw PostPushNum in CTermView:DrawChar().

5). Fix a bug of buffer overflow in CTermData::InsertChar(). p.s. Though the function is not used now.
  • Loading branch information
hwangcc23 committed Apr 18, 2016
1 parent c69e6ab commit 0e6b5f4
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 36 deletions.
153 changes: 131 additions & 22 deletions src/core/termdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,23 +167,24 @@ CTermData::~CTermData()
void CTermData::SetScreenSize( int RowCount, unsigned short RowsPerPage,
unsigned short ColsPerPage)
{
m_RowsPerPage = RowsPerPage;
// if cols per page change, reallocate all existing rows.
if( m_ColsPerPage != ColsPerPage )
{
for(int i=0; i < m_RowCount; i++)
{
char* NewLine = AllocNewLine(ColsPerPage);
unsigned short Cols = (ColsPerPage < m_ColsPerPage)?ColsPerPage:m_ColsPerPage;
//Copy context of old into new one.
memcpy(NewLine, m_Screen[i], Cols);
memcpy(GetLineAttr(NewLine, ColsPerPage), GetLineAttr(m_Screen[i]), sizeof(CTermCharAttr::AttrType)*Cols);
delete []m_Screen[i];
m_Screen[i] = NewLine;
}
m_ColsPerPage = ColsPerPage;
}
SetRowCount(RowCount);
m_RowsPerPage = RowsPerPage;
// if cols per page change, reallocate all existing rows.
if( m_ColsPerPage != ColsPerPage )
{
for(int i=0; i < m_RowCount; i++)
{
char* NewLine = AllocNewLine(ColsPerPage);
unsigned short Cols = (ColsPerPage < m_ColsPerPage)?ColsPerPage:m_ColsPerPage;
//Copy context of old into new one.
memcpy(NewLine, m_Screen[i], Cols);
memcpy(GetLineAttr(NewLine, ColsPerPage), GetLineAttr(m_Screen[i]), sizeof(CTermCharAttr::AttrType)*Cols);
*GetPostPushNum(NewLine) = *GetPostPushNum(m_Screen[i]);
delete []m_Screen[i];
m_Screen[i] = NewLine;
}
m_ColsPerPage = ColsPerPage;
}
SetRowCount(RowCount);
}

// Change row count of screen buffer
Expand Down Expand Up @@ -226,11 +227,19 @@ void CTermData::AllocScreenBuf(int RowCount, unsigned short RowsPerPage,unsigned
}

// Initialize new lines
void CTermData::InitNewLine(char* NewLine, const int ColsPerPage){
void CTermData::InitNewLine(char* NewLine, const int ColsPerPage)
{
memset( NewLine, ' ', ColsPerPage);

NewLine[ColsPerPage] = '\0';
CTermCharAttr DefAttr; DefAttr.SetToDefault(); DefAttr.SetNeedUpdate(true);

CTermCharAttr DefAttr;
DefAttr.SetToDefault();
DefAttr.SetNeedUpdate(true);
memset16( GetLineAttr(NewLine, ColsPerPage), DefAttr.AsType(), ColsPerPage);

unsigned char *num = GetPostPushNum(NewLine);
*num = 0;
}

// LF handler
Expand Down Expand Up @@ -342,6 +351,8 @@ void CTermData::PutChar(unsigned char ch)

m_Screen[m_CaretPos.y][m_CaretPos.x] = ch;

NumberingPostPush( m_CaretPos.y );

CTermCharAttr* pAttr = GetLineAttr( m_Screen[m_CaretPos.y] );

// Check if we've changed a character which is part of a URL.
Expand Down Expand Up @@ -424,6 +435,7 @@ void CTermData::ScrollUp(int n /*=1*/)
{
memset( m_Screen[end+i], ' ', m_ColsPerPage-1 );
memset16( GetLineAttr(m_Screen[end+i]), m_CurAttr.AsType(), m_ColsPerPage-1 );
*GetPostPushNum(m_Screen[end+i]) = 0;
SetWholeLineUpdate(m_Screen[end+i]);
}
}
Expand All @@ -447,6 +459,7 @@ void CTermData::ScrollDown(int n /*=1*/)
{
memset( m_Screen[end-i], ' ', m_ColsPerPage-1 );
memset16( GetLineAttr(m_Screen[end-i]), m_CurAttr.AsType(), m_ColsPerPage-1 );
*GetPostPushNum(m_Screen[end-i]) = 0;
SetWholeLineUpdate(m_Screen[end-i]);
}
}
Expand Down Expand Up @@ -630,7 +643,9 @@ void CTermData::ClearScreen(int p)
if( i < m_RowsPerPage)
break;
memcpy( tmp, m_Screen[i-m_RowsPerPage],m_ColsPerPage);
memcpy( GetLineAttr(tmp),GetLineAttr(m_Screen[i-m_RowsPerPage]),m_ColsPerPage); }
memcpy( GetLineAttr(tmp),GetLineAttr(m_Screen[i-m_RowsPerPage]),m_ColsPerPage);
*GetPostPushNum(tmp) = *GetPostPushNum(m_Screen[i-m_RowsPerPage]);
}
break;
case 0: // Erase from current position to end (inclusive)
default:
Expand All @@ -647,7 +662,9 @@ void CTermData::ClearScreen(int p)
if( i < m_RowsPerPage)
break;
memcpy( tmp, m_Screen[i-m_RowsPerPage],m_ColsPerPage);
memcpy( GetLineAttr(tmp),GetLineAttr(m_Screen[i-m_RowsPerPage]),m_ColsPerPage); }
memcpy( GetLineAttr(tmp),GetLineAttr(m_Screen[i-m_RowsPerPage]),m_ColsPerPage);
*GetPostPushNum(tmp) = *GetPostPushNum(m_Screen[i-m_RowsPerPage]);
}
break;
}
}
Expand Down Expand Up @@ -1288,7 +1305,7 @@ void CTermData::InsertChar( int line, int col, int n )
CTermCharAttr* pattr = GetLineAttr( pline );

int coln = col + n;
for( int end = m_ColsPerPage; end >= coln; end-- )
for( int end = m_ColsPerPage - 1; end >= coln; end-- )
{
pline[ end ] = pline[ end - n ];
pattr[ end ] = pattr[ end - n ];
Expand Down Expand Up @@ -1425,3 +1442,95 @@ void CTermData::OnLineModified(int row UNUSED)
// This function can be overriden in derived class.
}

bool CTermData::PostPushHeaderTest(int iLine)
{
char *line = m_Screen[iLine];
int col;

// FIXME: Hack to detect PostPushHeader on PTT. Have a general method?
if( line[0] == '-' && line[1] == '-' )
{
for( col = 2; col < m_ColsPerPage; col++ )
{
if( line[col] != ' ' )
return false;
}
return true;
}

return false;
}

bool CTermData::PostPushTest(int iLine)
{
char *line = m_Screen[iLine];

// FIXME: Hack to detect PostPush on PTT. Have a general method?
if( line[0] == '\xb1' && line[1] == '\xc0' && line[2] == ' ' ) // like
return true;
if( line[0] == '\xbc' && line[1] == '\x4e' && line[2] == ' ' ) // dislike
return true;
if( line[0] == '\xa1' && line[1] == '\xf7' && line[2] == ' ' ) // line continuation
return true;

return false;
}

void CTermData::NumberingPostPush(int iLine)
{
unsigned char num = 0;
int row;

*GetPostPushNum(m_Screen[iLine]) = 0;

if( !PostPushTest(iLine) )
{
return ;
}

for( row = iLine - 1; row >= m_FirstLine; row-- )
{
if( PostPushHeaderTest(row) )
{
num = 1;
goto Numbering;
}

if( PostPushTest(row) )
{
num = *GetPostPushNum( m_Screen[row] );
if( num )
{
//num += iLine - row;
num++;
goto Numbering;
}
}
}

for( row = iLine + 1; row < m_RowsPerPage; row++ )
{
if( PostPushHeaderTest(row) )
{
goto Numbering;
}

if( PostPushTest(row) )
{
num = *GetPostPushNum( m_Screen[row] );
if( num )
{
//num -= iLine + row;
num--;
goto Numbering;
}
}
}

Numbering:
if( num > 0 )
{
*GetPostPushNum( m_Screen[iLine] ) = num;

}
}
17 changes: 13 additions & 4 deletions src/core/termdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ class X_EXPORT CTermData
return ( CTermCharAttr* ) ( pLine + m_ColsPerPage + 1 );
}

unsigned char* GetPostPushNum( const char* pLine )
{
return ( unsigned char* ) ( pLine + m_ColsPerPage + 1 + m_ColsPerPage * sizeof( CTermCharAttr::AttrType ) );
}

//Get all text from (0,0) to (maxX, maxY), if trim is true, it return text
//without tail black spaces.
string GetAllText( bool trim = true )
Expand All @@ -227,6 +232,7 @@ class X_EXPORT CTermData
#endif
void UpdateDisplay();
void DoUpdateDisplay();
void NumberingPostPush();
static void memset16( void* dest, short val, size_t n );
void ParseAnsiColor( const char* pParam );
void EraseLine( int p );
Expand Down Expand Up @@ -277,11 +283,11 @@ class X_EXPORT CTermData
// Allocate new lines
char* AllocNewLine( const int ColsPerPage )
{
// struct{ char[ColsPerPage], char='\0', CTermCharAttr[ColsPerPage]}
// struct{ char[ColsPerPage], char='\0', CTermCharAttr[ColsPerPage, char=0]}
// Neversay:The structure is show below:
// [ ColsPerPage*char + '\0' + ColsPerPage*CTermCharAttr ]
// so size is: ColsPerPage*1 + 1 + ColsPerPage*sizeof(CTermCharAttr)
char * NewLine = new char[ 1 + ColsPerPage * ( 1 + sizeof( CTermCharAttr::AttrType ) ) ];
// [ ColsPerPage*char + '\0' + ColsPerPage*CTermCharAttr + PostPushNum ]
// so size is: ColsPerPage*1 + 1 + ColsPerPage*sizeof(CTermCharAttr) + 1
char * NewLine = new char[ 1 + ColsPerPage * ( 1 + sizeof( CTermCharAttr::AttrType ) ) + 1 ];

InitNewLine( NewLine, ColsPerPage );
return NewLine;
Expand All @@ -292,6 +298,9 @@ class X_EXPORT CTermData
void AllocScreenBuf( int RowCount, unsigned short RowsPerPage, unsigned short ColsPerPage );
virtual void OnLineModified( int row );

bool PostPushHeaderTest(int iLine);
bool PostPushTest(int iLine);
void NumberingPostPush(int iLine);

///////////////////////////////////////////////////////////////////
//Data Field Section
Expand Down
65 changes: 55 additions & 10 deletions src/core/termview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ bool CTermView::DrawSpaceFillingChar(const char* ch, int len UNUSED, int x, int
return false;
}

int CTermView::DrawChar(int row, int col)
int CTermView::DoDrawChar(int row, int col, const char *str, CTermCharAttr *pAttr)
{
GdkDrawable* dc = m_Widget->window;
if(!GDK_IS_DRAWABLE(dc) && m_XftDraw == NULL)
Expand All @@ -378,11 +378,9 @@ int CTermView::DrawChar(int row, int col)
return 1;
}

const char* pLine = m_pTermData->m_Screen[m_pTermData->m_FirstLine + row];
CTermCharAttr* pAttr = m_pTermData->GetLineAttr(pLine);
int w = 2;
bool is_mbcs2 = false;
switch( pAttr[col].GetCharSet() )
switch( pAttr->GetCharSet() )
{
case CTermCharAttr::CS_MBCS1:
break;
Expand All @@ -397,8 +395,6 @@ int CTermView::DrawChar(int row, int col)
// case CTermCharAttr::CS_ASCII:
w = 1;
}
pLine += col;
pAttr += col;

int loop_times = w;
bool bSel[2];
Expand Down Expand Up @@ -465,21 +461,21 @@ int CTermView::DrawChar(int row, int col)

if( !pAttr[i].IsBlink() || m_ShowBlink ) // If text should be drawn.
{
if( ' ' != *pLine && '\0' != *pLine )
if( ' ' != *str && '\0' != *str )
{
gsize wl = 0;
gchar* utf8 = NULL;

/* UAO display support */
switch (m_UAO) {
case 2:
utf8 = uao250_b2u(pLine, w, &wl);
utf8 = uao250_b2u(str, w, &wl);
break;
case 1:
utf8 = uao241_b2u(pLine, w, &wl);
utf8 = uao241_b2u(str, w, &wl);
break;
default:
utf8 = g_convert(pLine, w, "UTF-8", m_pTermData->m_Encoding.c_str(), NULL, &wl, NULL);
utf8 = g_convert(str, w, "UTF-8", m_pTermData->m_Encoding.c_str(), NULL, &wl, NULL);
break;
}

Expand Down Expand Up @@ -536,6 +532,55 @@ int CTermView::DrawChar(int row, int col)
return is_mbcs2 ? 1 : w;
}

int CTermView::DrawChar(int row, int col)
{
const char* pLine = m_pTermData->m_Screen[m_pTermData->m_FirstLine + row];
CTermCharAttr* pAttr = m_pTermData->GetLineAttr(pLine);
int number, n;
char num_buff[16];

n = 0;
pLine += col;
pAttr += col;

if( m_pTermData->PostPushTest(m_pTermData->m_FirstLine + row) )
{
number = *(m_pTermData->GetPostPushNum(m_pTermData->m_Screen[m_pTermData->m_FirstLine + row]));
if( number == 0 )
n = 0;
else
n = snprintf( num_buff, 16, "%dF ", number );
}

if( n != 0 && col >= 3 )
{
if( col == 3 )
{
// Draw PostPushNum
CTermCharAttr DefAttr;
DefAttr.SetToDefault();
DefAttr.SetNeedUpdate(true);
for( int i = 0; i < n; i++ )
{
DoDrawChar(row, col + i, num_buff + i, &DefAttr);
}
}
col += n;
}

if( col < m_pTermData->m_ColsPerPage)
{
return DoDrawChar(row, col, pLine, pAttr);
}
else
{
if( pAttr->GetCharSet() == CTermCharAttr::CS_MBCS1)
return 2;
else
return 1;
}
}

void CTermView::PointToLineCol(int *x, int *y, bool *left)
{
*x -= m_LeftMargin;
Expand Down
2 changes: 2 additions & 0 deletions src/core/termview.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "view.h"
#include "caret.h"
#include "termdata.h"

#include <string>

Expand All @@ -52,6 +53,7 @@ friend class CTermData;
virtual bool PreKeyDown(GdkEventKey *evt);
virtual bool OnKeyDown(GdkEventKey* evt);
virtual void OnTextInput(const gchar* string);
int DoDrawChar(int row, int col, const char *str, CTermCharAttr *pAttr);
int DrawChar(int row, int col);
void PointToLineCol(int *x, int *y, bool *left = NULL);

Expand Down

0 comments on commit 0e6b5f4

Please sign in to comment.