Here is my contribution:
1. Custom SQL lexer registered and implemented directly in ctlSQLBox
class.
I've done this to detect AS '....' construction.
Everything inside quotes after AS will be highlighted as in regular SQL
code. Escaped quotes (\') are also detected correctly.
Now, the more preferable way to edit/update stored procedures will be
using Query window (instead of Properties dialog). So, just select a
function, click SQL on toolbar and edit the code. Once your change is
ready just click "Play" and the procedure will updated in the DB. Way
more convenient, isn't it?
2. More keywords added such as UNIUON, INNER, OUTER, etc.
3. Find Dialog. Press Ctrl-F in any SQL box to activate Find dialog.
No regular expressions though, since wx UI does not support that in its
Find dialog. Custom Find dialog needs to be implemented for that.
4. Edit Menu in Query window. I also added Edit menu to the Query
window.
RCS file: /disk1/cvsroot/pgadmin3/src/include/ctlSQLBox.h,v
retrieving revision 1.5
diff -r1.5 ctlSQLBox.h
16a17
> #include <wx/fdrepdlg.h>
24a26,27
> wxFindReplaceData m_findData;
> wxFindReplaceDialog* m_dlgFind;
28a32,33
> void OnFind(wxCommandEvent& event);
> void OnFindDialog(wxFindDialogEvent& event);
RCS file: /disk1/cvsroot/pgadmin3/src/ui/frmQuery.cpp,v
retrieving revision 1.16
diff -r1.16 frmQuery.cpp
104a105,108
> editMenu->AppendSeparator();
> editMenu->Append(MNU_FIND, wxT("&Find..."), wxT("Find"),
wxITEM_NORMAL);
>
> menuBar->Append(editMenu, wxT("&Edit"));
433a438,439
> //simply delegate this menu command to the contol
> sqlQuery->OnFind(ev);
RCS file: /disk1/cvsroot/pgadmin3/src/ui/ctlSQLBox.cpp,v
retrieving revision 1.7
diff -r1.7 ctlSQLBox.cpp
18a19,32
> #include <stdlib.h>
> #include <string.h>
> #include <ctype.h>
> #include <stdio.h>
> #include <stdarg.h>
>
> #include "Platform.h"
> #include "PropSet.h"
> #include "Accessor.h"
> #include "KeyWords.h"
> #include "Scintilla.h"
> #include "SciLexer.h"
>
> #include "menu.h"
22c36
< CASE CAST CHECKPOINT CLASS CLOSE CLUSTER COMMENT COMMIT
CONVERSION CONSTRAINT COPY CREATE CURSOR \
---
> CASCADE CASE CAST CHECKPOINT CLASS CLOSE CLUSTER COMMENT
COMMIT CONVERSION CONSTRAINT COPY CREATE CURSOR \
25,26c39,40
< HAVING ILIKE IMMUTABLE IN INDEX INSERT INTO IS JOIN KEY
LANGUAGE LIKE LISTEN LOAD LOCK MOVE NOT NOTIFY NULL \
< OIDS ON OPERATOR OPTION OR ORDER PREPARE PRIMARY PROCEDURE
REINDEX REPLACE RESET RETURN RETURNS REVOKE ROLLBACK ROW RULE \
---
> HAVING ILIKE IMMUTABLE IN INDEX INNER INSERT INTO IS JOIN KEY
LANGUAGE LIKE LISTEN LOAD LOCK MOVE NOT NOTIFY NULL \
> OIDS ON OPERATOR OPTION OR ORDER OUTER PREPARE PRIMARY
PROCEDURE REINDEX REFERENCES REPLACE RESET RETURN RETURNS REVOKE
ROLLBACK ROW RULE \
28c42,214
< UNLISTEN UPDATE USING VACUUM VALUES VIEW VOLATILE WHEN WHERE
WITH WITHOUT")
---
> UNION UNLISTEN UPDATE USING VACUUM VALUES VIEW VOLATILE WHEN
WHERE WITH WITHOUT")
>
> static void classifyWordSQL(unsigned int start, unsigned int end,
WordList &keywords, Accessor &styler, wxString& lastWord) {
> char s[100];
> bool wordIsNumber = isdigit(styler[start]) || (styler[start] ==
'.');
> for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
> s[i] = static_cast<char>(toupper(styler[start + i]));
> s[i + 1] = '\0';
> }
> lastWord = s;
> char chAttr = SCE_C_IDENTIFIER;
> if (wordIsNumber)
> chAttr = SCE_C_NUMBER;
> else {
> if (keywords.InList(s))
> chAttr = SCE_C_WORD;
> }
> styler.ColourTo(end, chAttr);
> }
>
> static void ColouriseSQLDoc(unsigned int startPos, int length,
> int initStyle, WordList *keywordlists[],
Accessor &styler) {
>
> WordList &keywords = *keywordlists[0];
>
> styler.StartAt(startPos);
>
> bool fold = styler.GetPropertyInt("fold") != 0;
> int lineCurrent = styler.GetLine(startPos);
> int spaceFlags = 0;
>
> wxString lastWord;
>
> int state = initStyle;
>
> bool bInFunctionDefinition;
> if (lineCurrent > 0) {
> styler.SetLineState(lineCurrent,
styler.GetLineState(lineCurrent-1));
> bInFunctionDefinition =
(styler.GetLineState(lineCurrent) == 1);
> } else {
> styler.SetLineState(lineCurrent, 0);
> bInFunctionDefinition = false;
> }
>
> char chPrev = ' ';
> char chNext = styler[startPos];
> styler.StartSegment(startPos);
> unsigned int lengthDoc = startPos + length;
> for (unsigned int i = startPos; i < lengthDoc; i++) {
> char ch = chNext;
> chNext = styler.SafeGetCharAt(i + 1);
>
> if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
> int indentCurrent =
styler.IndentAmount(lineCurrent, &spaceFlags);
> int lev = indentCurrent;
> if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
> // Only non whitespace lines can be
headers
> int indentNext =
styler.IndentAmount(lineCurrent + 1, &spaceFlags);
> if (indentCurrent < (indentNext &
~SC_FOLDLEVELWHITEFLAG)) {
> lev |= SC_FOLDLEVELHEADERFLAG;
> }
> }
> if (fold) {
> styler.SetLevel(lineCurrent, lev);
> }
> lineCurrent++;
> styler.SetLineState(lineCurrent,
(bInFunctionDefinition? 1 : 0));
> }
>
> if (styler.IsLeadByte(ch)) {
> chNext = styler.SafeGetCharAt(i + 2);
> chPrev = ' ';
> i += 1;
> continue;
> }
>
> if (state == SCE_C_DEFAULT) {
> if (iswordstart(ch)) {
> styler.ColourTo(i - 1, state);
> state = SCE_C_WORD;
> } else if (ch == '/' && chNext == '*') {
> styler.ColourTo(i - 1, state);
> state = SCE_C_COMMENT;
> } else if (ch == '-' && chNext == '-') {
> styler.ColourTo(i - 1, state);
> state = SCE_C_COMMENTLINE;
> } else if (ch == '\'') {
> styler.ColourTo(i - 1, state);
> if (bInFunctionDefinition && chPrev !=
'\\') {
> bInFunctionDefinition = false;
> styler.SetLineState(lineCurrent,
0);
> } else if (!bInFunctionDefinition &&
lastWord.IsSameAs("AS", false)) {
> bInFunctionDefinition = true;
> styler.SetLineState(lineCurrent,
1);
> } else {
> state = SCE_C_STRING;
> if (chPrev == '\\') {
> styler.ColourTo(i - 1,
state);
> }
> }
> } else if (isoperator(ch)) {
> styler.ColourTo(i - 1, state);
> styler.ColourTo(i, SCE_C_OPERATOR);
> }
> } else if (state == SCE_C_WORD) {
> if (!iswordchar(ch)) {
>
classifyWordSQL(styler.GetStartSegment(), i - 1, keywords, styler,
lastWord);
> state = SCE_C_DEFAULT;
> if (ch == '/' && chNext == '*') {
> state = SCE_C_COMMENT;
> } else if (ch == '-' && chNext == '-') {
> state = SCE_C_COMMENTLINE;
> } else if (ch == '\'') {
> state = SCE_C_STRING;
> } else if (isoperator(ch)) {
> styler.ColourTo(i,
SCE_C_OPERATOR);
> }
> }
> } else {
> if (state == SCE_C_COMMENT) {
> if (ch == '/' && chPrev == '*') {
> if (((i >
(styler.GetStartSegment() + 2)) || ((initStyle == SCE_C_COMMENT) &&
> (styler.GetStartSegment() ==
startPos)))) {
> styler.ColourTo(i,
state);
> state = SCE_C_DEFAULT;
> }
> }
> } else if (state == SCE_C_COMMENTLINE) {
> if (ch == '\r' || ch == '\n') {
> styler.ColourTo(i - 1, state);
> state = SCE_C_DEFAULT;
> }
> } else if (state == SCE_C_STRING) {
> if (ch == '\'') {
> if ( chNext == '\'' ) {
> i++;
> } else {
> styler.ColourTo(i,
state);
> state = SCE_C_DEFAULT;
> i++;
> }
> ch = chNext;
> chNext = styler.SafeGetCharAt(i
+ 1);
> }
> }
> if (state == SCE_C_DEFAULT) { // One of the
above succeeded
> if (ch == '/' && chNext == '*') {
> state = SCE_C_COMMENT;
> } else if (ch == '-' && chNext == '-') {
> state = SCE_C_COMMENTLINE;
> } else if (ch == '\'') {
> if (bInFunctionDefinition && chPrev !=
'\\') {
> bInFunctionDefinition = false;
>
styler.SetLineState(lineCurrent, 0);
> } else if (!bInFunctionDefinition &&
lastWord.IsSameAs("AS", false)) {
> bInFunctionDefinition = true;
> styler.SetLineState(lineCurrent,
1);
> } else {
> state = SCE_C_STRING;
> }
> } else if (iswordstart(ch)) {
> state = SCE_C_WORD;
> } else if (isoperator(ch)) {
> styler.ColourTo(i,
SCE_C_OPERATOR);
> }
> }
> }
> chPrev = ch;
> }
> styler.ColourTo(lengthDoc - 1, state);
> }
>
> LexerModule lmPostgreSQL(SCLEX_AUTOMATIC, ColouriseSQLDoc, "sql");
32a219,224
> EVT_MENU(MNU_FIND,ctlSQLBox::OnFind)
> EVT_FIND(-1, ctlSQLBox::OnFindDialog)
> EVT_FIND_NEXT(-1, ctlSQLBox::OnFindDialog)
> EVT_FIND_REPLACE(-1, ctlSQLBox::OnFindDialog)
> EVT_FIND_REPLACE_ALL(-1, ctlSQLBox::OnFindDialog)
> EVT_FIND_CLOSE(-1, ctlSQLBox::OnFindDialog)
37c229,230
< : wxStyledTextCtrl(parent,id , pos, size, style)
---
> : wxStyledTextCtrl(parent,id , pos, size, style),
> m_dlgFind(NULL)
81c274
< SetLexer(wxSTC_LEX_SQL);
---
> SetLexer(lmPostgreSQL.GetLanguage());
83a277,282
>
> wxAcceleratorEntry entries[1];
> entries[0].Set(wxACCEL_CTRL, (int)'F',
MNU_FIND);
> wxAcceleratorTable accel(1, entries);
> SetAcceleratorTable(accel);
> m_findData.SetFlags(wxFR_DOWN);
89a289,291
> if (event.m_controlDown && event.m_keyCode == 'F') {
> //allow Ctrl-F accelerator
> } else {
91a294
> }
94a298,357
> void ctlSQLBox::OnFind(wxCommandEvent& ev)
> {
> if (!m_dlgFind) {
> wxFindReplaceDialog* m_dlgFind = new wxFindReplaceDialog(this,
&m_findData, _T("Find"), 0);
> m_dlgFind->Show(TRUE);
> }
> }
>
> void ctlSQLBox::OnFindDialog(wxFindDialogEvent& event)
> {
> wxEventType type = event.GetEventType();
>
> if ( type == wxEVT_COMMAND_FIND || type == wxEVT_COMMAND_FIND_NEXT
)
> {
> int flags = 0;
> if (event.GetFlags() & wxFR_MATCHCASE) {
> flags |= SCFIND_MATCHCASE;
> }
> if (event.GetFlags() & wxFR_WHOLEWORD) {
> flags |= SCFIND_WHOLEWORD;
> }
> int startPos = GetSelectionStart();
> int endPos = SendMsg(SCI_GETTEXTLENGTH, 0, 0);
> if (event.GetFlags() & wxFR_DOWN) {
> startPos += 1;
> } else {
> endPos = 0;
> startPos -= 1;
> }
>
> int pos = FindText(startPos, endPos,
event.GetFindString().c_str(), flags);
> if (pos >= 0) {
> SetSelectionStart(pos);
> SetSelectionEnd(pos + event.GetFindString().Length());
> EnsureCaretVisible();
> } else {
> wxMessageBox(wxT("Reached end of the document"),
> wxT("Find"),
> wxICON_EXCLAMATION | wxOK, this);
> }
> }
> else if ( type == wxEVT_COMMAND_FIND_REPLACE ||
> type == wxEVT_COMMAND_FIND_REPLACE_ALL )
> {
> wxMessageBox(wxT("Not implemented"),
> wxT("Find"),
> wxICON_EXCLAMATION | wxOK, this);
> }
> else if ( type == wxEVT_COMMAND_FIND_CLOSE )
> {
> wxFindReplaceDialog *dlg = event.GetDialog();
> m_dlgFind = NULL;
> dlg->Destroy();
> }
> else
> {
> wxLogError(wxT("Unknown find dialog event!"));
> }
> }
>
97a361,365
> if (m_dlgFind) {
> m_dlgFind->Destroy();
> m_dlgFind = NULL;
> }
>
98a367,368
>
>
-----Original Message-----
From: Andreas Pflug [mailto:Andreas.Pflug@web.de]
Sent: Saturday, May 31, 2003 4:48 PM
To: Yurgis Baykshtis; Dave Page
Subject: Re: [pgadmin-hackers] Find Dialog in SQL box (Admin3)?
Yurgis Baykshtis wrote:
>Yes, I would love to contribute.
>I have a working code already based on wx Find dialog.
>No whole words and regexp options though but it does the work.
>
>Now what is the process of the code integration?
>Will you give me write access to CVS?
>
Yurgis,
please send the output of "cvs diff" to Dave, and he will merge your
code to cvs.
Regards,
Andreas