[geany/geany-plugins] cf11e6: reworked so use variable markers for better compatibility with other plugins.
William Fraser
git-noreply at xxxxx
Wed Apr 18 15:29:41 UTC 2012
Branch: refs/heads/master
Author: William Fraser <william.fraser at virgin.net>
Committer: William Fraser <william.fraser at virgin.net>
Date: Wed, 18 Apr 2012 15:29:41
Commit: cf11e635d2f94fea73e973eada789f29d573a960
https://github.com/geany/geany-plugins/commit/cf11e635d2f94fea73e973eada789f29d573a960
Log Message:
-----------
reworked so use variable markers for better compatibility with other plugins.
Modified Paths:
--------------
geanynumberedbookmarks/src/geanynumberedbookmarks.c
Modified: geanynumberedbookmarks/src/geanynumberedbookmarks.c
325 files changed, 227 insertions(+), 98 deletions(-)
===================================================================
@@ -34,26 +34,18 @@
static const gchar base64_int_to_char[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-/* offset for marker numbers used - to bypass markers used by normal bookmarksetc */
-#define BOOKMARK_BASE 10
-
/* define structures used in this plugin */
typedef struct FileData
{
gchar *pcFileName; /* holds filename */
gint iBookmark[10]; /* holds bookmark lines or -1 for not set */
+ gint iBookmarkMarkerUsed[10]; /*holds which marker (2-24) is used for this bookmark */
gint iBookmarkLinePos[10]; /* holds position of cursor in line */
gchar *pcFolding; /* holds which folds are open and which not */
gint LastChangedTime; /* time file was last changed by this editor */
struct FileData * NextNode;
} FileData;
-/* structure to hold list of Scintilla objects that have had icons set for bookmarks */
-typedef struct SCIPOINTERHOLDER
-{
- ScintillaObject* sci;
- struct SCIPOINTERHOLDER * NextNode;
-} SCIPOINTERHOLDER;
GeanyPlugin *geany_plugin;
GeanyData *geany_data;
@@ -71,7 +63,6 @@
/* internal variables */
static gint iShiftNumbers[]={41,33,34,163,36,37,94,38,42,40};
-static SCIPOINTERHOLDER *sciList=NULL;
static FileData *fdKnownFilesSettings=NULL;
static gulong key_release_signal_id;
@@ -584,61 +575,192 @@ static void LoadSettings(void)
}
-/* Define Markers for an editor */
-static void DefineMarkers(ScintillaObject* sci)
-{
- gint i;
- for(i=0;i<10;i++)
- scintilla_send_message(sci,SCI_MARKERDEFINEPIXMAP,i+BOOKMARK_BASE,
- (glong)(aszMarkerImages[i]));
-}
-
+/* get next free marker number */
+static gint NextFreeMarker(ScintillaObject* sci) {
+ gint i,l,m,k;
+ guint32 markers;
+ FileData *fd;
-/* Make sure that have setup markers if not come across this particular editor
- * Keep track of editors we've encountered and set markers for
-*/
-static void CheckEditorSetup(void)
-{
- SCIPOINTERHOLDER *sciTemp;
- ScintillaObject* sci=document_get_current()->editor->sci;
+ markers=(guint32)(g_object_get_data(G_OBJECT(sci),"Geany_Numbered_Bookmarks_Used"));
- /* no recorded editors so make note of editor */
- if(sciList==NULL)
+ /* markers 0 and 1 reserved for bookmarks & errors, 25 onwards for folds */
+ /* find first free marker after last defined marker. Will ensure that new marker */
+ /* is displayed over any previously set markers */
+ for(i=24,m=-1;i>1;i--)
{
- if((sciList=(SCIPOINTERHOLDER *)(g_malloc(sizeof *sciTemp)))!=NULL)
+ l=scintilla_send_message(sci,SCI_MARKERSYMBOLDEFINED,i,0);
+
+ if(l==SC_MARK_CIRCLE || l==SC_MARK_AVAILABLE)
{
- sciList->sci=sci;
- sciList->NextNode=NULL;
- DefineMarkers(sci);
+ /* if reached start of user-defined markers then return this */
+ if(i==2)
+ return 2;
+
+ /* found empty marker so make note of it */
+ m=i;
+ /* keep looking for 1st unused marker after last used marker */
+ continue;
}
- return;
+ /* found marker */
+
+ /* if not a numbered bookmark then ignore it */
+ if((markers&(1<<i))==0)
+ continue;
+
+ /* if have found an empty marker higher then return this */
+ if(m!=-1)
+ return m;
+
+ /* no empty markers above last used */
+
+ /* first see if there are any unused markers */
+ while(i>1)
+ {
+ l=scintilla_send_message(sci,SCI_MARKERSYMBOLDEFINED,i,0);
+ if(l==SC_MARK_CIRCLE || l==SC_MARK_AVAILABLE)
+ break;
+
+ i--;
+ }
+
+ /* no empty markers available so return -1 */
+ if(i==1)
+ return -1;
+
+ /* there are empty markers available. Break out of for loop & make them available */
+ break;
}
- sciTemp=sciList;
- while(sciTemp->NextNode!=NULL)
+ /* compact used numbered markers */
+ /* move through markers moving numbered bookmarks ones from i to m */
+ for(m=2,i=2;i<25;i++)
{
- /* if have come across this editor before, then it will have had it's markers set and we
- * don't need to do any more
- */
- if(sciTemp->sci==sci)
- return;
+ /* don't move marker unless it's a numbered bookmark marker */
+ if((markers&(1<<i))==0)
+ continue;
- sciTemp=sciTemp->NextNode;
+ /* find unused marker */
+ l=scintilla_send_message(sci,SCI_MARKERSYMBOLDEFINED,m,0);
+ while((l!=SC_MARK_CIRCLE && l!=SC_MARK_AVAILABLE) && m<i)
+ {
+ m++;
+ l=scintilla_send_message(sci,SCI_MARKERSYMBOLDEFINED,m,0);
+ }
+
+ /* if can't move marker forward then don't */
+ if(m==i)
+ continue;
+
+ /* move marker from i to m */
+ /* first make note of line number of marker */
+ l=scintilla_send_message(sci,SCI_MARKERNEXT,0,1<<i);
+ /* remove old marker */
+ scintilla_send_message(sci,SCI_MARKERDELETEALL,i,0);
+ scintilla_send_message(sci,SCI_MARKERDEFINE,i,SC_MARK_AVAILABLE);
+
+ /* find bookmark number, put in k */
+ fd=GetFileData(document_get_current()->file_name);
+ for(k=0;k<10;k++)
+ if(fd->iBookmarkMarkerUsed[k]==i)
+ break;
+
+ /* insert new marker */
+ scintilla_send_message(sci,SCI_MARKERDEFINEPIXMAP,m,(glong)(aszMarkerImages[k]));
+ scintilla_send_message(sci,SCI_MARKERADD,l,m);
+
+ /* update markers record */
+ markers-=1<<i;
+ markers|=1<<m;
+
+ /* update record of which bookmark uses which marker */
+ fd->iBookmarkMarkerUsed[k]=m;
}
- /* if have come across this editor before, then it will have had it's markers set and we don't
- * need to do any more
- */
- if(sciTemp->sci==sci)
- return;
- /* not come across this editor */
- if((sciTemp->NextNode=g_malloc(sizeof *sciTemp->NextNode))!=NULL)
+ /* save record of which markers are being used */
+ g_object_set_data(G_OBJECT(sci),"Geany_Numbered_Bookmarks_Used",(gpointer)markers);
+
+
+ /* m should point to last used marker. Next free marker should lie after this */
+ /* find free marker & return it */
+ for(;m<25;m++)
{
- sciTemp->NextNode->sci=sci;
- sciTemp->NextNode->NextNode=NULL;
- DefineMarkers(sci);
- }
+ l=scintilla_send_message(sci,SCI_MARKERSYMBOLDEFINED,m,0);
+ if(l==SC_MARK_CIRCLE || l==SC_MARK_AVAILABLE)
+ return m;
+ }
+
+ /* no empty markers available so return -1 */
+ /* in theory shouldn't get here but leave just in case my logic is flawed */
+ return -1;
+}
+
+
+static void SetMarker(ScintillaObject* sci,gint bookmarkNumber,gint markerNumber,gint line)
+{
+ guint32 markers;
+ FileData *fd;
+
+ /* insert new marker */
+ scintilla_send_message(sci,SCI_MARKERDEFINEPIXMAP,markerNumber,
+ (glong)(aszMarkerImages[bookmarkNumber]));
+ scintilla_send_message(sci,SCI_MARKERADD,line,markerNumber);
+
+ /* update record of which bookmark uses which marker */
+ fd=GetFileData(document_get_current()->file_name);
+ fd->iBookmarkMarkerUsed[bookmarkNumber]=markerNumber;
+
+ /* update record of which markers are being used */
+ markers=(guint32)(g_object_get_data(G_OBJECT(sci),"Geany_Numbered_Bookmarks_Used"));
+ markers|=1<<markerNumber;
+ g_object_set_data(G_OBJECT(sci),"Geany_Numbered_Bookmarks_Used",(gpointer)markers);
+}
+
+
+static void DeleteMarker(ScintillaObject* sci,gint bookmarkNumber,gint markerNumber)
+{
+ guint32 markers;
+
+ /* remove marker */
+ scintilla_send_message(sci,SCI_MARKERDELETEALL,markerNumber,0);
+ scintilla_send_message(sci,SCI_MARKERDEFINE,markerNumber,SC_MARK_AVAILABLE);
+
+ /* update record of which markers are being used */
+ markers=(guint32)(g_object_get_data(G_OBJECT(sci),"Geany_Numbered_Bookmarks_Used"));
+ markers-=1<<markerNumber;
+ g_object_set_data(G_OBJECT(sci),"Geany_Numbered_Bookmarks_Used",(gpointer)markers);
+}
+
+
+static void ApplyBookmarks(ScintillaObject* sci,FileData *fd)
+{
+ gint i,iLineCount,m;
+ GtkWidget *dialog;
+
+ iLineCount=scintilla_send_message(sci,SCI_GETLINECOUNT,0,0);
+
+ for(i=0;i<10;i++)
+ if(fd->iBookmark[i]!=-1 && fd->iBookmark[i]<iLineCount)
+ {
+ m=NextFreeMarker(sci);
+ /* if run out of markers report this */
+ if(m==-1)
+ {
+ dialog=gtk_message_dialog_new(GTK_WINDOW(geany->main_widgets->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,GTK_BUTTONS_NONE,
+ _("Unable to apply all markers to \
+ '%s' as all being used."),
+ document_get_current()->file_name);
+ gtk_dialog_add_button(GTK_DIALOG(dialog),_("_Okay"),GTK_RESPONSE_OK);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ return;
+ }
+
+ /* otherwise ok to set marker */
+ SetMarker(sci,i,m,fd->iBookmark[i]);
+ }
}
@@ -658,10 +780,6 @@ static void on_document_open(GObject *obj, GeanyDocument *doc, gpointer user_dat
/* keep compiler happy & initialise iBits: will logically be initiated anyway */
gint iBits=0,iFlags,iBitCounter;
- /* ensure have markers set */
- CheckEditorSetup();
- DefineMarkers(sci);
-
/* check to see if file has changed since geany last saved it */
fd=GetFileData(doc->file_name);
if(stat(doc->file_name,&sBuf)==0 && fd!=NULL && fd->LastChangedTime!=-1 &&
@@ -686,9 +804,7 @@ static void on_document_open(GObject *obj, GeanyDocument *doc, gpointer user_dat
/* file not changed since Geany last saved it so saved settings should be fine */
case GTK_RESPONSE_ACCEPT:
/* now set markers */
- for(i=0;i<10;i++)
- if(fd->iBookmark[i]!=-1)
- scintilla_send_message(sci,SCI_MARKERADD,fd->iBookmark[i],i+BOOKMARK_BASE);
+ ApplyBookmarks(sci,fd);
/* get fold settings if present and want to use them */
if(fd->pcFolding==NULL || bRememberFolds==FALSE)
@@ -728,11 +844,7 @@ static void on_document_open(GObject *obj, GeanyDocument *doc, gpointer user_dat
break;
/* file has changed since Geany last saved but, try to load bookmarks anyway */
case GTK_RESPONSE_REJECT:
- iLineCount=scintilla_send_message(sci,SCI_GETLINECOUNT,0,0);
- for(i=0;i<10;i++)
- if(fd->iBookmark[i]!=-1 && fd->iBookmark[i]<iLineCount)
- scintilla_send_message(sci,SCI_MARKERADD,fd->iBookmark[i],i);
-
+ ApplyBookmarks(sci,fd);
break;
default: /* default - don't try to set markers */
break;
@@ -745,7 +857,7 @@ static void on_document_open(GObject *obj, GeanyDocument *doc, gpointer user_dat
*/
static void on_document_save(GObject *obj, GeanyDocument *doc, gpointer user_data)
{
- FileData *fdTemp;
+ FileData *fd;
gint i,iLineCount,iFlags,iBitCounter=0;
ScintillaObject* sci=doc->editor->sci;
struct stat sBuf;
@@ -754,9 +866,10 @@ static void on_document_save(GObject *obj, GeanyDocument *doc, gpointer user_dat
gboolean bHasClosedFold=FALSE;
/* update markerpos */
- fdTemp=GetFileData(doc->file_name);
+ fd=GetFileData(doc->file_name);
for(i=0;i<10;i++)
- fdTemp->iBookmark[i]=scintilla_send_message(sci,SCI_MARKERNEXT,0,1<<(i+BOOKMARK_BASE));
+ fd->iBookmark[i]=scintilla_send_message(sci,SCI_MARKERNEXT,0,
+ 1<<(fd->iBookmarkMarkerUsed[i]));
/* update fold state */
iLineCount=scintilla_send_message(sci,SCI_GETLINECOUNT,0,0);
@@ -792,14 +905,15 @@ static void on_document_save(GObject *obj, GeanyDocument *doc, gpointer user_dat
}
/* transfer data to text string if have closed fold. Default will leave them open*/
- fdTemp->pcFolding=(!bHasClosedFold)?NULL:g_strndup((gchar*)(gbaFoldData->data),gbaFoldData->len);
+ fd->pcFolding=(!bHasClosedFold)?NULL:g_strndup((gchar*)(gbaFoldData->data),
+ gbaFoldData->len);
/* free byte array space */
g_byte_array_free(gbaFoldData,TRUE);
/* make note of time last saved */
if(stat(doc->file_name,&sBuf)==0)
- fdTemp->LastChangedTime=sBuf.st_mtime;
+ fd->LastChangedTime=sBuf.st_mtime;
/* save settings */
SaveSettings();
@@ -949,7 +1063,9 @@ static void GotoBookMark(gint iBookMark)
ScintillaObject* sci=document_get_current()->editor->sci;
FileData *fd;
- iLine=scintilla_send_message(sci,SCI_MARKERNEXT,0,1<<(iBookMark+BOOKMARK_BASE));
+ fd=GetFileData(document_get_current()->file_name);
+
+ iLine=scintilla_send_message(sci,SCI_MARKERNEXT,0,1<<(fd->iBookmarkMarkerUsed[iBookMark]));
/* ignore if no marker placed for requested bookmark */
if(iLine==-1)
@@ -967,7 +1083,6 @@ static void GotoBookMark(gint iBookMark)
break;
/* remembered line position */
case 1:
- fd=GetFileData(document_get_current()->file_name);
iPosition+=fd->iBookmarkLinePos[iBookMark];
if(iPosition>iEndOfLine)
iPosition=iEndOfLine;
@@ -1012,12 +1127,13 @@ static void GotoBookMark(gint iBookMark)
/* set (or remove) numbered bookmark */
static void SetBookMark(gint iBookMark)
{
- gint iNewLine,iOldLine,iPosInLine;
+ gint iNewLine,iOldLine,iPosInLine,m;
ScintillaObject* sci=document_get_current()->editor->sci;
- FileData *fd;
+ FileData *fd=GetFileData(document_get_current()->file_name);;
+ GtkWidget *dialog;
/* see if already such a bookmark present */
- iOldLine=scintilla_send_message(sci,SCI_MARKERNEXT,0,1<<(iBookMark+BOOKMARK_BASE));
+ iOldLine=scintilla_send_message(sci,SCI_MARKERNEXT,0,1<<(fd->iBookmarkMarkerUsed[iBookMark]));
iNewLine=GetLine(sci);
iPosInLine=scintilla_send_message(sci,SCI_GETCURRENTPOS,0,0)-
scintilla_send_message(sci,SCI_POSITIONFROMLINE,iNewLine,0);
@@ -1025,23 +1141,43 @@ static void SetBookMark(gint iBookMark)
/* if no marker then simply add one to current line */
if(iOldLine==-1)
{
- CheckEditorSetup();
- scintilla_send_message(sci,SCI_MARKERADD,iNewLine,iBookMark+BOOKMARK_BASE);
- fd=GetFileData(document_get_current()->file_name);
+ m=NextFreeMarker(sci);
+ /* if run out of markers report this */
+ if(m==-1)
+ {
+ dialog=gtk_message_dialog_new(GTK_WINDOW(geany->main_widgets->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,GTK_BUTTONS_NONE,
+ _("Unable to apply markers as all being used\
+ ."));
+ gtk_dialog_add_button(GTK_DIALOG(dialog),_("_Okay"),GTK_RESPONSE_OK);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ return;
+ }
+ /* otherwise ok to set marker */
+ SetMarker(sci,iBookMark,m,iNewLine);
fd->iBookmarkLinePos[iBookMark]=iPosInLine;
}
- /* else either have to remove marker from current line, or move it to current line */
+ /* else if have to remove marker from current line */
+ else if(iOldLine==iNewLine)
+ {
+ DeleteMarker(sci,iBookMark,fd->iBookmarkMarkerUsed[iBookMark]);
+ }
+ /* else have to move it to current line */
else
{
+ /* go through the process of removing and adding the marker so the marker will */
+ /* have the highest value and be on top */
+
/* remove old marker */
- scintilla_send_message(sci,SCI_MARKERDELETEALL,iBookMark+BOOKMARK_BASE,0);
+ DeleteMarker(sci,iBookMark,fd->iBookmarkMarkerUsed[iBookMark]);
/* add new marker if moving marker */
- if(iOldLine!=iNewLine)
- {
- scintilla_send_message(sci,SCI_MARKERADD,iNewLine,iBookMark+BOOKMARK_BASE);
- fd=GetFileData(document_get_current()->file_name);
- fd->iBookmarkLinePos[iBookMark]=iPosInLine;
- }
+ m=NextFreeMarker(sci);
+ /* don't bother checking for failure to find marker as have just released one so */
+ /* there should be one free */
+ SetMarker(sci,iBookMark,m,iNewLine);
+ fd->iBookmarkLinePos[iBookMark]=iPosInLine;
}
}
@@ -1160,10 +1296,9 @@ void plugin_cleanup(void)
gint k;
guint i;
ScintillaObject* sci;
- SCIPOINTERHOLDER *sciTemp;
- SCIPOINTERHOLDER *sciNext;
FileData *fdTemp=fdKnownFilesSettings;
FileData *fdTemp2;
+ guint32 markers;
/* uncouple keypress monitor */
g_signal_handler_disconnect(geany->main_widgets->window,key_release_signal_id);
@@ -1172,20 +1307,14 @@ void plugin_cleanup(void)
for(i=0;i<GEANY(documents_array)->len;i++)
if(documents[i]->is_valid) {
sci=documents[i]->editor->sci;
- for(k=0;k<9;k++)
- scintilla_send_message(sci,SCI_MARKERDELETEALL,BOOKMARK_BASE+k,0);
+ markers=(guint32)(g_object_get_data(G_OBJECT(sci),
+ "Geany_Numbered_Bookmarks_Used"));
+ for(k=2;k<25;k++)
+ if((markers&(1<<k))!=0)
+ scintilla_send_message(sci,SCI_MARKERDELETEALL,k,0);
}
- /* Clear memory used for list of editors */
- sciTemp=sciList;
- while(sciTemp!=NULL)
- {
- sciNext=sciTemp->NextNode;
- free(sciTemp);
- sciTemp=sciNext;
- }
-
/* Clear memory used to hold file details */
while(fdTemp!=NULL)
{
@@ Diff output truncated at 100000 characters. @@
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: TBD).
More information about the Plugins-Commits
mailing list