00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "parenmatcher.h"
00024
#include "paragdata.h"
00025
00026
#include <private/qrichtext_p.h>
00027
#include <qtextedit.h>
00028
#include <qapplication.h>
00029
00030 ParenMatcher::ParenMatcher()
00031 {
00032
enabled = TRUE;
00033 }
00034
00035 bool ParenMatcher::match( QTextCursor *cursor )
00036 {
00037
if ( !
enabled )
00038
return FALSE;
00039
bool ret = FALSE;
00040
00041
QChar c( cursor->paragraph()->at( cursor->index() )->c );
00042
bool ok1 = FALSE;
00043
bool ok2 = FALSE;
00044
if ( c ==
'{' || c ==
'(' || c ==
'[' ) {
00045 ok1 =
checkOpenParen( cursor );
00046 ret = ok1 || ret;
00047 }
else if ( cursor->index() > 0 ) {
00048 c = cursor->paragraph()->at( cursor->index() - 1 )->c;
00049
if ( c ==
'}' || c ==
')' || c ==
']' ) {
00050 ok2 =
checkClosedParen( cursor );
00051 ret = ok2 || ret;
00052 }
00053 }
00054
return ret;
00055 }
00056
00057 bool ParenMatcher::checkOpenParen( QTextCursor *cursor )
00058 {
00059
if ( !cursor->paragraph()->extraData() )
00060
return FALSE;
00061
QValueList<Symbol> parenList = ( (
ParagData*)cursor->paragraph()->extraData() )->symbolList();
00062
00063
Symbol openParen, closedParen;
00064 QTextParagraph *closedParenParag = cursor->paragraph();
00065
00066
int i = 0;
00067
int ignore = 0;
00068
bool foundOpen = FALSE;
00069
QChar c = cursor->paragraph()->at( cursor->index() )->c;
00070
for (;;) {
00071
if ( !foundOpen ) {
00072
if ( i >= (
int)parenList.count() )
00073
goto bye;
00074 openParen = parenList[ i ];
00075
if ( openParen.
pos() != cursor->index() ) {
00076 ++i;
00077
continue;
00078 }
else {
00079 foundOpen = TRUE;
00080 ++i;
00081 }
00082 }
00083
00084
if ( i >= (
int)parenList.count() ) {
00085
for (;;) {
00086 closedParenParag = closedParenParag->next();
00087
if ( !closedParenParag )
00088
goto bye;
00089
if ( closedParenParag->extraData() &&
00090 ( (
ParagData*)closedParenParag->extraData() )->symbolList().count() > 0 ) {
00091 parenList = ( (
ParagData*)closedParenParag->extraData() )->symbolList();
00092
break;
00093 }
00094 }
00095 i = 0;
00096 }
00097
00098 closedParen = parenList[ i ];
00099
if ( closedParen.
type() == Symbol::Left ) {
00100 ignore++;
00101 ++i;
00102
continue;
00103 }
else {
00104
if ( ignore > 0 ) {
00105 ignore--;
00106 ++i;
00107
continue;
00108 }
00109
00110
int id =
Match;
00111
if ( c ==
'{' && closedParen.
ch() !=
'}' ||
00112 c ==
'(' && closedParen.
ch() !=
')' ||
00113 c ==
'[' && closedParen.
ch() !=
']' )
00114
id =
Mismatch;
00115 cursor->document()->setSelectionStart(
id, *cursor );
00116
int tidx = cursor->index();
00117 QTextParagraph *tstring = cursor->paragraph();
00118 cursor->setParagraph( closedParenParag );
00119 cursor->setIndex( closedParen.
pos() + 1 );
00120 cursor->document()->setSelectionEnd(
id, *cursor );
00121 cursor->setParagraph( tstring );
00122 cursor->setIndex( tidx );
00123
return TRUE;
00124 }
00125 }
00126
00127 bye:
00128
return FALSE;
00129 }
00130
00131 bool ParenMatcher::checkClosedParen( QTextCursor *cursor )
00132 {
00133
if ( !cursor->paragraph()->extraData() )
00134
return FALSE;
00135
QValueList<Symbol> parenList = ( (
ParagData*)cursor->paragraph()->extraData() )->symbolList();
00136
00137
Symbol openParen, closedParen;
00138 QTextParagraph *openParenParag = cursor->paragraph();
00139
00140
int i = parenList.count() - 1;
00141
int ignore = 0;
00142
bool foundClosed = FALSE;
00143
QChar c = cursor->paragraph()->at( cursor->index() - 1 )->c;
00144
for (;;) {
00145
if ( !foundClosed ) {
00146
if ( i < 0 )
00147
goto bye;
00148 closedParen = parenList[ i ];
00149
if ( closedParen.
pos() != cursor->index() - 1 ) {
00150 --i;
00151
continue;
00152 }
else {
00153 foundClosed = TRUE;
00154 --i;
00155 }
00156 }
00157
00158
if ( i < 0 ) {
00159
for (;;) {
00160 openParenParag = openParenParag->prev();
00161
if ( !openParenParag )
00162
goto bye;
00163
if ( openParenParag->extraData() &&
00164 ( (
ParagData*)openParenParag->extraData() )->symbolList().count() > 0 ) {
00165 parenList = ( (
ParagData*)openParenParag->extraData() )->symbolList();
00166
break;
00167 }
00168 }
00169 i = parenList.count() - 1;
00170 }
00171
00172 openParen = parenList[ i ];
00173
if ( openParen.
type() == Symbol::Right ) {
00174 ignore++;
00175 --i;
00176
continue;
00177 }
else {
00178
if ( ignore > 0 ) {
00179 ignore--;
00180 --i;
00181
continue;
00182 }
00183
00184
int id =
Match;
00185
if ( c ==
'}' && openParen.
ch() !=
'{' ||
00186 c ==
')' && openParen.
ch() !=
'(' ||
00187 c ==
']' && openParen.
ch() !=
'[' )
00188
id =
Mismatch;
00189 cursor->document()->setSelectionStart(
id, *cursor );
00190
int tidx = cursor->index();
00191 QTextParagraph *tstring = cursor->paragraph();
00192 cursor->setParagraph( openParenParag );
00193 cursor->setIndex( openParen.
pos() );
00194 cursor->document()->setSelectionEnd(
id, *cursor );
00195 cursor->setParagraph( tstring );
00196 cursor->setIndex( tidx );
00197
return TRUE;
00198 }
00199 }
00200
00201 bye:
00202
return FALSE;
00203 }