Using folding in scintilla
scintilla is a script editing component http://www.scintilla.org for more information.


This setting up and using code-folding scintilla


First we create some constants for later use
static const int MARGIN_SCRIPT_FOLD_INDEX = 1;

Register the on margin click event for the window (this is windows specific)
static const int WINDOW_ID = 900;

BEGIN_MESSAGE_MAP(CDocumentWindow, CDocumentWindowsBaseClass)
  ON_NOTIFY(SCN_MARGINCLICK, WINDOW_ID, OnMarginClicked)
END_MESSAGE_MAP()

(WINDOW_ID is used in the CreateWindow call when you create the window)

Set the lexer you want to use...
(This will be done in the constructor or on create method...)
  SendEditor(SCI_SETLEXER, SCLEX_CPP);
  SendEditor(SCI_SETSTYLEBITS, 5);

Set some properties so the lexer knows what we want
  SendEditor(SCI_SETPROPERTY, (WPARAM)"fold", (LPARAM)"1");
  SendEditor(SCI_SETPROPERTY, (WPARAM)"fold.compact", (LPARAM)"0");

(The fold.compact option folds blank lines,
which I don't like, but by default it's on "1")

I also like:
  SendEditor(SCI_SETPROPERTY, (WPARAM)"fold.comment", (LPARAM)"1");
  SendEditor(SCI_SETPROPERTY, (WPARAM)"fold.preprocessor", (LPARAM)"1");

Now resize all the margins to zero
(This will be done in a RecalcLineMargin method...)
  SendEditor(SCI_SETMARGINWIDTHN, MARGIN_SCRIPT_FOLD_INDEX, 0);

Then set the margin type and margin mask and resize it...
  SendEditor(SCI_SETMARGINTYPEN,  MARGIN_SCRIPT_FOLD_INDEX, SC_MARGIN_SYMBOL);
  SendEditor(SCI_SETMARGINMASKN, MARGIN_SCRIPT_FOLD_INDEX, SC_MASK_FOLDERS);
  SendEditor(SCI_SETMARGINWIDTHN, MARGIN_SCRIPT_FOLD_INDEX, 20);

Set some visual preferences
  SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDER, SC_MARK_PLUS);
  SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEROPEN, SC_MARK_MINUS);
  SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEREND, SC_MARK_EMPTY);
  SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_EMPTY);
  SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEROPENMID, SC_MARK_EMPTY);
  SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERSUB, SC_MARK_EMPTY);
  SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY);

  SendEditor(SCI_SETFOLDFLAGS, 16, 0); // 16  	Draw line below if not expanded

Tell scintilla we want to be notified about mouse clicks in the margin
  SendEditor(SCI_SETMARGINSENSITIVEN, MARGIN_SCRIPT_FOLD_INDEX, 1);

Respond to SCN_MARGINCLICK events... (note that the method prototype is windows specific)
afx_msg void
CDocumentWindow::OnMarginClick(NMHDR* nmhdr, LRESULT* result)
{
  SCNotification* notify = (SCNotification*)nmhdr;

  const int modifiers = notify->modifiers;
  const int position = notify->position;
  const int margin = notify->margin;
  const int line_number = SendEditor(SCI_LINEFROMPOSITION, position, 0);

  switch (margin) {
    case MARGIN_SCRIPT_FOLD_INDEX:
    {
      SendEditor(SCI_TOGGLEFOLD, line_number, 0);
    }
    break;
  }
}

That should be enough to get it working.
You'll want to play around with it until you're happy with the way the folding works,
scintilla seems to use a much more complicated MarginClick...
Luckily harvesting the MarginClick code from scintilla is easy:

First change in OnMarginClick change:
      SendEditor(SCI_TOGGLEFOLD, line_number, 0);
To:
      MarginClick(position, modifiers);

Then in your header file...
  bool MarginClick(int position, int modifiers);
  void Expand(int &line, bool doExpand,
              bool force = false, int visLevels = 0, int level = -1);
  void FoldAll();

Then go and find those methods from SciTEBase.cxx and copy them to your code.

Oh, and you had better go update your Goto Line function now...
	SendEditor(SCI_ENSUREVISIBLEENFORCEPOLICY, line_number);
	SendEditor(SCI_GOTOLINE, line_number);


That's it, enjoy.
You can send any comments or suggestions about this to vascy@hotmail.com