1 /* Copyright (C) 2011-2013 by rickyrockrat <gpib at rickyrockrat dot net>
2 *
3 * This file is part of Parcellite.
4 *
5 * Parcellite is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Parcellite is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /** \file ******************************************************************
20 \n\b File: attr_list.c
21 \n\b Author: Doug Springer
22 \n\b Company: DNK Designs Inc.
23 \n\b Date: 01/09/2013 9:22 pm
24 \n\b Description: General attribute changing and list manipulation routines.
25 */ /************************************************************************
26 */
27
28 #include "parcellite.h"
29 /***************************************************************************/
30 /** Get the underline on the given lable, or allocate new one.
31 \n\b Arguments:
32 \n\b Returns:
33 ****************************************************************************/
get_underline_attr(GtkLabel * label)34 PangoAttrInt *get_underline_attr(GtkLabel *label)
35 {
36 PangoAttrList *attrs=gtk_label_get_attributes (label);
37 PangoAttribute *attr;
38
39 if (NULL == attrs){/**no existing list. Add one */
40 /*attrs = pango_attr_list_new ();
41 attr=NULL;*/
42 return(NULL);
43 }else{ /**grab attribte, if there is one. */
44 PangoAttrIterator* iter;
45 iter=pango_attr_list_get_iterator(attrs);
46 attr=pango_attr_iterator_get (iter,PANGO_ATTR_UNDERLINE);
47 pango_attr_iterator_destroy(iter);
48 }
49 return (PangoAttrInt *)attr;
50 }
51 /***************************************************************************/
52 /** Returns 0 if not strikethrough, 1 if it is.
53 \n\b Arguments:
54 \n\b Returns:
55 ****************************************************************************/
is_underline(GtkLabel * label)56 gboolean is_underline(GtkLabel *label)
57 {
58 PangoAttrInt *strike=get_underline_attr(label);
59 if(NULL == strike || strike->value == FALSE)
60 return FALSE;
61 return TRUE;
62 }
63
64 /***************************************************************************/
65 /** Set the strike through on/off. Create a new strike through and/or attr
66 list.
67 \n\b Arguments:
68 \n\b Returns:
69 ****************************************************************************/
set_underline(GtkLabel * label,gboolean mode)70 void set_underline(GtkLabel *label, gboolean mode)
71 {
72 PangoAttrInt *strike;
73 PangoAttrList *attrs;
74
75 strike=get_underline_attr(label);
76 if(NULL ==(attrs=gtk_label_get_attributes (label)) )
77 attrs = pango_attr_list_new ();
78
79 /** printf("strike=%p attrs=%p\n",strike,attrs); fflush(NULL);*/
80 if(NULL ==strike || strike->value != mode){
81 PangoAttribute *attr=pango_attr_underline_new(mode);
82 pango_attr_list_change (attrs, attr);
83 gtk_label_set_attributes (label, attrs);
84 }
85 }
86 /***************************************************************************/
87 /** Get the strikethrough on the given lable, or allocate new one.
88 \n\b Arguments:
89 \n\b Returns:
90 ****************************************************************************/
get_strikethrough_attr(GtkLabel * label)91 PangoAttrInt *get_strikethrough_attr(GtkLabel *label)
92 {
93 PangoAttrList *attrs=gtk_label_get_attributes (label);
94 PangoAttribute *attr;
95
96 if (NULL == attrs){/**no existing list. Add one */
97 /*attrs = pango_attr_list_new ();
98 attr=NULL;*/
99 return(NULL);
100 }else{ /**grab attribte, if there is one. */
101 PangoAttrIterator* iter;
102 iter=pango_attr_list_get_iterator(attrs);
103 attr=pango_attr_iterator_get (iter,PANGO_ATTR_STRIKETHROUGH);
104 pango_attr_iterator_destroy(iter);
105 }
106 if(0 && NULL == attr){ /**No existing strikethrough. Add the attribute. */
107 attr=pango_attr_strikethrough_new(FALSE);
108 pango_attr_list_change (attrs, attr);
109 gtk_label_set_attributes (label, attrs);
110 }
111 return (PangoAttrInt *)attr;
112 }
113
114 /***************************************************************************/
115 /** Returns 0 if not strikethrough, 1 if it is.
116 \n\b Arguments:
117 \n\b Returns:
118 ****************************************************************************/
is_strikethrough(GtkLabel * label)119 gboolean is_strikethrough(GtkLabel *label)
120 {
121 PangoAttrInt *strike=get_strikethrough_attr(label);
122 if(NULL == strike || strike->value == FALSE)
123 return FALSE;
124 return TRUE;
125 }
126
127 /***************************************************************************/
128 /** Set the strike through on/off. Create a new strike through and/or attr
129 list.
130 \n\b Arguments:
131 \n\b Returns:
132 ****************************************************************************/
set_strikethrough(GtkLabel * label,gboolean mode)133 void set_strikethrough(GtkLabel *label, gboolean mode)
134 {
135 PangoAttrInt *strike;
136 PangoAttrList *attrs;
137
138 strike=get_strikethrough_attr(label);
139 if(NULL ==(attrs=gtk_label_get_attributes (label)) )
140 attrs = pango_attr_list_new ();
141
142 /** printf("strike=%p attrs=%p\n",strike,attrs); fflush(NULL);*/
143 if(NULL ==strike || strike->value != mode){
144 PangoAttribute *attr=pango_attr_strikethrough_new(mode);
145 pango_attr_list_change (attrs, attr);
146 gtk_label_set_attributes (label, attrs);
147 }
148 }
149 /***************************************************************************/
150 /** Find the item in the delete list.
151 \n\b Arguments:
152 \n\b Returns:
153 ****************************************************************************/
find_h_item(GList * list,GtkWidget * w,GList * e)154 GList *find_h_item(GList *list,GtkWidget *w, GList *e)
155 {
156 GList *i;
157 for ( i=list; NULL != i; i=i->next){
158 struct s_item_info *it=(struct s_item_info *)i->data;
159 if( (NULL == w || it->item ==w) && it->element==e){/**found it */
160 /*printf("Found %p\n",i); fflush(NULL); */
161 return i;
162 }
163 }
164 return NULL;
165 }
166
167 /***************************************************************************/
168 /** Add an item to the history delete list.
169 \n\b Arguments:
170 \n\b Returns:
171 ****************************************************************************/
add_h_item(struct history_info * h,GtkWidget * w,GList * element,gint which)172 void add_h_item(struct history_info *h, GtkWidget *w, GList* element, gint which)
173 {
174 GList *ele;
175 GList *op=NULL;
176 switch(which){
177 case OPERATE_DELETE:
178 op=h->delete_list;
179 break;
180 case OPERATE_PERSIST:
181 op=h->persist_list;
182 break;
183 default:
184 g_fprintf(stderr,"Invalid list '%d'\n",which);
185 return;
186 }
187 struct s_item_info *i;
188 if(NULL == (ele=find_h_item(op,w,element) ) ){
189 if(NULL != (i=g_malloc(sizeof(struct s_item_info)) ) ){
190 i->item=w;
191 i->element=element;
192 switch(which){
193 case OPERATE_DELETE:
194 h->delete_list=g_list_prepend(op,(gpointer)i);
195 break;
196 case OPERATE_PERSIST:
197 h->persist_list=g_list_prepend(op,(gpointer)i);
198 break;
199 }
200
201 /*g_printf("Added w %p e %p %p\n",w,element,h->delete_list); fflush(NULL); */
202 }/*else g_fprintf(stderr,"%s: NULL allocating element for delete list!\n",__func__); */
203 }/*else g_printf("found element??\n"); */
204 }
205
206 /***************************************************************************/
207 /** Delete an item from the history delete list.
208 h->delete_list is a GList. The data points to a struct s_item_info, which
209 contains a widget and an element - these latter two are part of the history
210 menu, so we just need to de-allocate the delete_list structure, and delete it
211 from the list.
212 \n\b Arguments:
213 \n\b Returns:
214 ****************************************************************************/
rm_h_item(struct history_info * h,GtkWidget * w,GList * element,gint which)215 void rm_h_item(struct history_info *h, GtkWidget *w, GList* element, gint which)
216 {
217 GList *i;
218 GList *op;
219 switch(which){
220 case OPERATE_DELETE:
221 op=h->delete_list;
222 break;
223 case OPERATE_PERSIST:
224 op=h->persist_list;
225 break;
226 }
227 if(NULL != (i=find_h_item(op,w,element) ) ){
228 /*printf("Freeing %p\n",i->data); */
229 g_free(i->data);
230 i->data=NULL;
231 /*fflush(NULL); */
232 switch(which){
233 case OPERATE_DELETE:
234 h->delete_list=g_list_delete_link(op,i);
235 break;
236 case OPERATE_PERSIST:
237 h->persist_list=g_list_delete_link(op,i);
238 break;
239 }
240 /** printf("Removed %p\n",i); fflush(NULL);*/
241 }
242
243 }
244
245
246 /***************************************************************************/
247 /** .
248 \n\b Arguments:
249 \n\b Returns:
250 ****************************************************************************/
remove_deleted_items(struct history_info * h)251 void remove_deleted_items(struct history_info *h)
252 {
253 if(NULL != h && NULL != h->delete_list){/**have a list of items to delete. */
254 GList *i;
255 g_mutex_lock(hist_lock);
256 /*g_print("Deleting items\n"); */
257 for (i=h->delete_list; NULL != i; i=i->next){
258 struct s_item_info *it=(struct s_item_info *)i->data;
259 /*printf("Free %p.. '%s' ",it->element->data,(char *)(it->((struct history_item *(element->data))->text))); */
260 g_free(it->element->data);
261 it->element->data=NULL;
262 history_list = g_list_delete_link(history_list, it->element);
263 /** printf("Free %p\n",it);
264 fflush(NULL);*/
265 g_free(it);
266 }
267 h->delete_list=NULL;
268 g_mutex_unlock(hist_lock);
269 if (get_pref_int32("save_history"))
270 save_history();
271 }
272 }
273 /***************************************************************************/
274 /** Handle marking for history window. Also manages adding/removing from
275 the delete list, which gets called when the history window closes.
276 \n\b Arguments:
277 \n\b Returns:
278 ****************************************************************************/
handle_marking(struct history_info * h,GtkWidget * w,gint index,gint which)279 void handle_marking(struct history_info *h, GtkWidget *w, gint index, gint which)
280 {
281 GtkLabel *l=(GtkLabel *)(gtk_bin_get_child((GtkBin*)w)) ;
282 GList* element = g_list_nth(history_list, index);
283 if(OPERATE_DELETE == which){
284 if(is_strikethrough(l)){ /**un-highlight */
285 set_strikethrough(l,FALSE);
286 rm_h_item(h,w,element,OPERATE_DELETE);
287 }
288 else {
289 /*g_printf("marking %p ",element); */
290 set_strikethrough(l,TRUE);
291 add_h_item(h,w,element,OPERATE_DELETE);
292 }
293 }else if(OPERATE_PERSIST == which){
294 struct history_item *c=(struct history_item *)(element->data);
295 if(NULL !=c){
296 if(c->flags & CLIP_TYPE_PERSISTENT)
297 c->flags&=~(CLIP_TYPE_PERSISTENT);
298 else
299 c->flags|=CLIP_TYPE_PERSISTENT;
300 h->change_flag|=CLIP_TYPE_PERSISTENT;
301 }
302 if(is_underline(l)){ /**un-highlight */
303 set_underline(l,FALSE);
304 rm_h_item(h,w,element,OPERATE_PERSIST);
305 }
306 else {
307 set_underline(l,TRUE);
308 add_h_item(h,w,element,OPERATE_PERSIST);
309 }
310 }
311
312 }
313
314