00001
00018 #define GITK_LIB_C
00019 #define GITK_TOOLS_C
00020
00021 #include "gitkincludes.h"
00022
00023
00029 static void gitk_dialog_dump_walker(xmlNodePtr cur,const gint level) {
00030 gint i;
00031 xmlChar *elem,*attr;
00032 xmlNsPtr nsptr;
00033
00034 while(cur != NULL) {
00035 if(xmlNodeIsText(cur)) {
00036
00037 if(!xmlIsBlankNode(cur)) {
00038 if((elem=xmlNodeGetContent(cur))) {
00039 print_ansi(ANSI_COLOR_DARKGRAY);for(i=0;i<level;i++) gitk_dump("..");
00040 gitk_dump1(ANSI_COLOR_LIGHTBLUE"%s"ANSI_COLOR_LIGHTGRAY"\n",elem);
00041 xmlFree(elem);
00042 }
00043 }
00044 }
00045 else {
00046
00047 print_ansi(ANSI_COLOR_DARKGRAY);for(i=0;i<level;i++) gitk_dump("..");
00048 nsptr=cur->ns;
00049 if(nsptr && (nsptr->prefix)) {
00050 gitk_dump2(ANSI_COLOR_WHITE"%s:%s",(xmlChar *)nsptr->prefix,cur->name);
00051 }
00052 else {
00053 gitk_dump1(ANSI_COLOR_WHITE"%s",cur->name);
00054 }
00055
00056
00057
00058
00059
00060
00061
00062
00063 if(!strncasecmp(cur->name,"widget",7)) {
00064 if((attr=xmlGetProp(cur,"id"))) {
00065 gitk_dump1(ANSI_COLOR_LIGHTRED" id=\"%s\"",attr);
00066 xmlFree(attr);
00067 }
00068 if((attr=xmlGetProp(cur,"type"))) {
00069 gitk_dump1(ANSI_COLOR_LIGHTRED" type=\"%s\"",attr);
00070 xmlFree(attr);
00071 }
00072 if((attr=xmlGetProp(cur,"hasFocus"))) {
00073 gitk_dump1(ANSI_COLOR_LIGHTRED" hasFocus=\"%s\"",attr);
00074 xmlFree(attr);
00075 }
00076 }
00077 gitk_dump(ANSI_COLOR_LIGHTGRAY"\n");
00078 }
00079
00080 if(cur->children!=NULL) gitk_dialog_dump_walker(cur->children,level+1);
00081 cur = cur->next;
00082 }
00083 }
00084
00085
00090 void gitk_dialog_dump(xmlDocPtr const doc) {
00091 if( (doc!=NULL)) {
00092 gitk_dialog_dump_walker(xmlDocGetRootElement(doc),0);
00093 print_ansi(ANSI_COLOR_LIGHTGRAY);
00094 }
00095 else if(doc==NULL) gitk_log("doc is empty");
00096 }
00097
00098
00105 xmlXPathObjectPtr gitk_xpath_type_filter(xmlXPathObjectPtr xpath_optr,const xmlXPathObjectType type) {
00106 if(xpath_optr && (xpath_optr->type!=type)) {
00107 gitk_err2("xpath expr does not returned the expected type: ist=%ld <-> soll=%ld",(unsigned long)xpath_optr->type,(unsigned long)type);
00108 xmlXPathFreeObject(xpath_optr);
00109 xpath_optr=NULL;
00110 }
00111 return(xpath_optr);
00112 }
00113
00114
00123 xmlXPathObjectPtr gitk__cxpath_get_object(GitkDialogPtr const dialog,GitkDialogAccessType access_type,xmlXPathCompExprPtr const xpath_comp_expression, xmlNodePtr const root_node) {
00124 xmlXPathObjectPtr result=NULL;
00125 xmlXPathContextPtr ctxt;
00126 xmlDocPtr doc;
00127
00128 g_assert(dialog!=NULL);
00129
00130
00131
00132 if((doc=gitk__dialog_get_doc(dialog,access_type))) {
00133 if((ctxt=xmlXPathNewContext(doc))) {
00134 if(root_node) ctxt->node=root_node;
00135 else ctxt->node=xmlDocGetRootElement(doc);
00136 if((!xmlXPathRegisterNs(ctxt,GITK_NS_PREFIX,GITK_NS_URL))
00137 && (!xmlXPathRegisterNs(ctxt,"dc","http://purl.org/dc/elements/1.1/"))) {
00138 result=xmlXPathCompiledEval(xpath_comp_expression,ctxt);
00139 xmlXPathRegisteredNsCleanup(ctxt);
00140 }
00141 else gitk_err("failed to register \"giml\" or \"dc\" namespace");
00142 xmlXPathFreeContext(ctxt);
00143 }
00144 else gitk_err("failed to get xpath context");
00145 }
00146 else gitk_err("failed to get dst doc");
00147
00148 return(result);
00149 }
00150
00151
00160 xmlXPathObjectPtr gitk__xpath_get_object(GitkDialogPtr const dialog,GitkDialogAccessType access_type,gchar * const xpath_expression, xmlNodePtr const root_node) {
00161 xmlXPathObjectPtr result=NULL;
00162 xmlXPathCompExprPtr xpath_comp_expression;
00163
00164 g_assert(dialog!=NULL);
00165
00166
00167 if((xpath_comp_expression=xmlXPathCompile(xpath_expression))) {
00168 result=gitk__cxpath_get_object(dialog,access_type,xpath_comp_expression,root_node);
00169 }
00170 else { gitk_err1("failed to compile xpath expression \"%s\"",xpath_expression); }
00171 return(result);
00172 }
00173
00174
00183 gchar *gitk__cxpath_get_string(GitkDialogPtr const dialog,GitkDialogAccessType access_type,xmlXPathCompExprPtr const xpath_comp_expression, xmlNodePtr const root_node) {
00184 gchar *result=NULL;
00185 xmlXPathObjectPtr xpath_optr;
00186
00187
00188 if((xpath_optr=gitk__cxpath_get_object(dialog,access_type,xpath_comp_expression,root_node))) {
00189 xpath_optr=xmlXPathConvertString(xpath_optr);
00190
00191 result=strdup(xmlXPathCastToString(xpath_optr));
00192 xmlXPathFreeObject(xpath_optr);
00193 }
00194 else gitk_err("failed to eval xpath expr");
00195 return(result);
00196 }
00197
00198
00207 gchar *gitk__xpath_get_string(GitkDialogPtr const dialog,GitkDialogAccessType access_type,gchar * const xpath_expression, xmlNodePtr const root_node) {
00208 gchar *result=NULL;
00209 xmlXPathCompExprPtr xpath_comp_expression;
00210
00211
00212 if((xpath_comp_expression=xmlXPathCompile(xpath_expression))) {
00213 result=gitk__cxpath_get_string(dialog,access_type,xpath_comp_expression,root_node);
00214 xmlXPathFreeCompExpr(xpath_comp_expression);
00215 }
00216 else { gitk_err1("failed to compile xpath expression \"%s\"",xpath_expression); }
00217 return(result);
00218 }
00219
00220
00229 xmlNodePtr gitk__cxpath_get_node(GitkDialogPtr const dialog,GitkDialogAccessType access_type,xmlXPathCompExprPtr const xpath_comp_expression, xmlNodePtr const root_node) {
00230 xmlNodePtr node=NULL;
00231 xmlXPathObjectPtr xpath_optr;
00232
00233
00234
00235
00236 if((xpath_optr=gitk_xpath_type_filter(
00237 gitk__cxpath_get_object(dialog,access_type,xpath_comp_expression,root_node),
00238 XPATH_NODESET))) {
00239 const xmlNodeSetPtr ns=(xmlNodeSetPtr)xpath_optr->nodesetval;
00240
00241 if(xmlXPathNodeSetGetLength(ns)==1) {
00242 node=xmlXPathNodeSetItem(ns,0);
00243 }
00244 else { gitk_log1("nodeset should contain exactly one node (but has %d nodes)",xmlXPathNodeSetGetLength(ns)); }
00245 xmlXPathFreeObject(xpath_optr);
00246 }
00247 else { gitk_err("failed to eval xpath expr"); }
00248
00249 return(node);
00250 }
00251
00252
00261 xmlNodePtr gitk__xpath_get_node(GitkDialogPtr const dialog,GitkDialogAccessType access_type,gchar * const xpath_expression, xmlNodePtr const root_node) {
00262 xmlXPathCompExprPtr xpath_comp_expression;
00263 xmlNodePtr node=NULL;
00264
00265
00266 if((xpath_comp_expression=xmlXPathCompile(xpath_expression))) {
00267 node=gitk__cxpath_get_node(dialog,access_type,xpath_comp_expression,root_node);
00268 xmlXPathFreeCompExpr(xpath_comp_expression);
00269 }
00270 else { gitk_err1("failed to compile xpath expression \"%s\"",xpath_expression); }
00271 return(node);
00272 }
00273
00274
00279 gchar *gitk_get_widget_xpath_expression(const gchar * const widget_id) {
00280 static gchar qstr[100+GITK_CONTROL_ID_MAXLEN];
00281 gint sl;
00282
00283 sl=strlen(widget_id);
00284 snprintf(qstr,99+GITK_CONTROL_ID_MAXLEN,"//"GITK_NS_PREFIX":widget[@id=\"%s\"]",widget_id);
00285 return(qstr);
00286 }
00287
00288
00294 gchar *gitk_get_widget_child_xpath_expression(const gchar * const widget_id,const gchar * const widget_value) {
00295 static gchar qstr[100+GITK_CONTROL_ID_MAXLEN];
00296 gint sl;
00297
00298 sl=strlen(widget_id)+strlen(widget_value);
00299 snprintf(qstr,99+GITK_CONTROL_ID_MAXLEN,"//"GITK_NS_PREFIX":widget[@id=\"%s\"]/"GITK_NS_PREFIX":%s",widget_id,widget_value);
00300 return(qstr);
00301 }
00302
00303
00311 void gitk_dialog_safe_new_child(xmlNsPtr const ns,xmlNodePtr const parent,gchar * const name,gchar * const content) {
00312 xmlNodePtr cur;
00313 gboolean already_exists=FALSE;
00314
00315 if((cur=parent->children)!=NULL) {
00316 while(cur) {
00317 if(!xmlNodeIsText(cur) && !strcasecmp(cur->name,name)) {
00318 already_exists=TRUE;
00319 break;
00320 }
00321 cur=cur->next;
00322 }
00323 }
00324 if(!already_exists) {
00325 xmlNewChild(parent,ns,name,content);
00326 }
00327 }
00328
00329
00337 char *parse_commandline_arg(guint * const argc, gchar *** const argv, guint * const i, gchar * const argn) {
00338 gchar *arg;
00339 gchar *argn2;
00340 guint argn2l;
00341
00342 gitk_log2("%s(\"%s\") beg",__FUNCTION__,argn);
00343
00344 g_assert(argc!=NULL);
00345 g_assert(argv!=NULL);
00346 g_assert(i!=NULL);
00347 g_assert(argn!=NULL);
00348 g_assert(((*argv)[*i])!=NULL);
00349
00350 argn2l=strlen(argn);
00351 argn2=alloca(argn2l+2);
00352 strcpy(argn2,argn);
00353 strcat(argn2,"=");
00354
00355 if(!strcmp(argn,(*argv)[*i]) || !strncmp(argn2,(*argv)[*i],argn2l+1)) {
00356 gitk_log(" matches, now extract arg");
00357 arg=(*argv)[*i]+argn2l;
00358
00359 if(*arg=='=') arg++;
00360 else if((*i)+1<*argc) {
00361 (*argv)[*i] = NULL;
00362 (*i)++;
00363 arg=(*argv)[*i];
00364 }
00365 else {
00366 gitk_log1("%s()=null end",__FUNCTION__);
00367 return(NULL);
00368 }
00369 gitk_log(" discarding parameter");
00370 (*argv)[*i]=NULL;
00371 gitk_log(" found something");
00372 if(arg && *arg) {
00373 gitk_log1("%s()=arg end",__FUNCTION__);
00374 return(arg);
00375 }
00376 }
00377 gitk_log1("%s()=null end",__FUNCTION__);
00378 return(NULL);
00379 }
00380
00381
00387 void cleanup_commandline_args(guint * const argc, gchar *** const argv) {
00388 guint i,j,k;
00389
00390 for (i = 1; i < *argc; i++) {
00391 for (k = i; k < *argc; k++) {
00392 if ((*argv)[k] != NULL) break;
00393 }
00394 if (k > i) {
00395 k -= i;
00396 for (j = i + k; j < *argc; j++) {
00397 (*argv)[j-k] = (*argv)[j];
00398 }
00399 *argc -= k;
00400 }
00401 }
00402 }
00403
00408 int gitk_puts(const char *utf8) {
00409 gchar *loc,*cs;
00410 int res;
00411
00412 #ifdef ENABLE_NLS
00413 cs=nl_langinfo(CODESET);
00414 #else
00415 cs="ISO-8859-1";
00416 #endif
00417 loc=g_convert(utf8,-1,cs,"UTF-8",NULL,NULL,NULL);
00418 res=puts(loc);
00419 g_free(loc);
00420 return(res);
00421 }
00422
00428 int gitk_printf(const char *utf8,...) {
00429 gchar *loc,*cs;
00430 va_list args;
00431 int res;
00432
00433 #ifdef ENABLE_NLS
00434 cs=nl_langinfo(CODESET);
00435 #else
00436 cs="ISO-8859-1";
00437 #endif
00438 loc=g_convert(utf8,-1,cs,"UTF-8",NULL,NULL,NULL);
00439 va_start(args,utf8);
00440 res=vprintf(loc,args);
00441 va_end(args);
00442 g_free(loc);
00443 return(res);
00444 }