[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