00001
00028 #define GITK_LIB_C
00029 #define GITK_DIALOG_C
00030
00031 #include "gitkincludes.h"
00032
00033
00034
00043 GitkDialogPtr gitk_dialog_new_from_file(gchar * const filename) {
00044 GitkDialogPtr dialog=NULL;
00045 xmlParserCtxtPtr ctxt;
00046
00047 g_assert(filename!=NULL);
00048 g_assert(*filename);
00049
00050 if((ctxt=xmlCreateFileParserCtxt(filename))) {
00051 dialog=gitk_dialog_new_from_parser_context(ctxt);
00052 xmlFreeParserCtxt(ctxt);
00053 }
00054 else gitk_err1("failed to create file-parser context for \"%s\"",filename);
00055 return(dialog);
00056 }
00057
00058
00068 GitkDialogPtr gitk_dialog_new_from_memory(gchar * const buffer, const guint size) {
00069 GitkDialogPtr dialog=NULL;
00070 xmlParserCtxtPtr ctxt;
00071
00072 g_assert(buffer!=NULL);
00073 g_assert(*buffer);
00074 g_assert(size);
00075
00076 if((ctxt=xmlCreateMemoryParserCtxt(buffer,size))) {
00077 dialog=gitk_dialog_new_from_parser_context(ctxt);
00078 xmlFreeParserCtxt(ctxt);
00079 }
00080 else gitk_err("failed to create memory-parser context");
00081 return(dialog);
00082 }
00083
00084
00093 GitkDialogPtr gitk_dialog_new_from_string(gchar * const str) {
00094 GitkDialogPtr dialog=NULL;
00095 xmlParserCtxtPtr ctxt;
00096
00097 g_assert(str!=NULL);
00098 g_assert(*str);
00099
00100 if((ctxt=xmlCreateMemoryParserCtxt(str,strlen(str)))) {
00101 dialog=gitk_dialog_new_from_parser_context(ctxt);
00102 xmlFreeParserCtxt(ctxt);
00103 }
00104 else gitk_err("failed to create memory-parser context");
00105 return(dialog);
00106 }
00107
00108
00118 GitkDialogPtr gitk_dialog_new_from_parser_context(xmlParserCtxtPtr const ctxt) {
00119 GitkDialogPtr dialog=NULL;
00120
00121 g_assert(ctxt!=NULL);
00122
00123
00124 #ifdef USE_DTD_VALIDATION
00125 ctxt->validate=TRUE;
00126 #else
00127 ctxt->validate=FALSE;
00128 #endif
00129 xmlParseDocument(ctxt);
00130 gitk_log2("parsed document is %s valid and %s well formed",(ctxt->valid?"":"not"),(ctxt->wellFormed?"":"not"));
00131 if(!ctxt->valid) {
00132 gitk_set_error(GITK_ERROR_INVALID_DOCUMENT,_("the supplied document is not a XML/GIML document"));
00133 }
00134 else if(!ctxt->wellFormed) {
00135 gitk_set_error(GITK_ERROR_INVALID_DOCUMENT,_("the supplied document is not a wellformed XML document"));
00136 }
00137 else dialog=gitk_dialog_new(ctxt->myDoc);
00138 return(dialog);
00139 }
00140
00141
00148 void gitk_dialog_free(GitkDialogPtr const dialog) {
00149 if(dialog) {
00150
00151 if(dialog->callback_list) {
00152 GList* node=g_list_first(dialog->callback_list);
00153 GitkCallbackNodePtr callback_node;
00154 while(node) {
00155 callback_node=(GitkCallbackNodePtr)node->data;
00156 g_free(callback_node->widget_id);
00157 g_free(callback_node->callback_name);
00158 g_free(callback_node);
00159 node=g_list_next(node);
00160 }
00161 g_list_free(dialog->callback_list);
00162 }
00163 if(dialog->src) xmlFreeDoc(dialog->src);
00164 if(dialog->dst) xmlFreeDoc(dialog->dst);
00165 if(dialog->lock) g_mutex_free(dialog->lock);
00166 g_free(dialog);
00167 }
00168 }
00169
00170
00176 static gboolean gitk_dialog_validate(GitkDialogPtr const dialog) {
00177 xmlNodePtr cur;
00178 gboolean result=TRUE;
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 if(!dialog->src) {
00195 gitk_log("xmlDoc src is null");
00196 gitk_set_error(GITK_ERROR_EMPTY_DOCUMENT,_("an empty document has been supplied"));
00197 result=FALSE;
00198 }
00199 else if((cur=xmlDocGetRootElement(dialog->src))==NULL) {
00200 gitk_log("xmlDoc src is empty");
00201 gitk_set_error(GITK_ERROR_EMPTY_DOCUMENT,_("an empty document has been supplied"));
00202 result=FALSE;
00203 }
00204 else if((dialog->ns=xmlSearchNsByHref(dialog->src,cur,(const xmlChar *)GITK_NS_URL))==NULL) {
00205 gitk_log("no namespace found in xmlDoc src");
00206 gitk_set_error(GITK_ERROR_WRONG_DOCTYPE_NAMESPACE,_("a document with a wrong document type namespace has been supplied"));
00207 result=FALSE;
00208 }
00209 else if(xmlStrcmp(cur->name,(const xmlChar *)"giml")) {
00210 gitk_log("wrong document type root node in xmlDoc src");
00211 gitk_set_error(GITK_ERROR_WRONG_DOCTYPE_ROOTNODE,_("a document with a wrong document type root node has been supplied"));
00212 result=FALSE;
00213 }
00214 if(result) {
00215 if(dialog->ns) {
00216 gitk_log2("namespace is \"%s\" at \"%s\"",gitk_save_get_string(dialog->ns->prefix),gitk_save_get_string(dialog->ns->href));
00217 }
00218 else {
00219 gitk_log("namespace is empty");
00220 }
00221 }
00222 return(result);
00223 }
00224
00225
00233 GitkDialogPtr gitk_dialog_new(xmlDocPtr const doc) {
00234 GitkDialogPtr dialog;
00235
00236 g_assert(doc!=NULL);
00237
00238 dialog=g_new0(GitkDialog,1);
00239 dialog->src=doc;
00240 dialog->dst=NULL;
00241 #ifdef G_THREADS_ENABLED
00242 if(!g_thread_supported()) g_thread_init(NULL);
00243 dialog->lock=g_mutex_new();
00244 #endif
00245 gitk_log1("dialog=0x%08lx",(unsigned long)dialog);
00246 gitk_log1("doc=0x%08lx",(unsigned long)dialog->src);
00247 if(gitk_dialog_validate(dialog)) {
00248 gitk_log("after loading");
00249 gitk_dialog_dump(dialog->src);
00250
00251 if(gitk_dialog_trans_initial(dialog)) {
00252 gitk_log("after initial transformations");
00253 gitk_dialog_dump(dialog->src);
00254 }
00255 else {
00256 gitk_dialog_free(dialog);
00257 dialog=NULL;
00258 }
00259 }
00260 else {
00261 gitk_dialog_free(dialog);
00262 dialog=NULL;
00263 }
00264 return(dialog);
00265 }
00266
00267
00273 xmlDocPtr gitk_dialog_get_src(GitkDialogPtr const dialog) {
00274 return(dialog->src);
00275 }
00276
00277
00285 xmlDocPtr gitk_dialog_get_dst(GitkDialogPtr const dialog) {
00286 if(!(dialog->dst)) {
00287 if(gitk_dialog_trans(dialog)) {
00288 gitk_log("after transformations");
00289 gitk_dialog_dump(dialog->dst);
00290 }
00291 else {
00292 gitk_log("error during transformation");
00293 }
00294 }
00295 return(dialog->dst);
00296 }
00297
00304 xmlDocPtr gitk__dialog_get_doc(GitkDialogPtr const dialog,GitkDialogAccessType access_type) {
00305 switch(access_type) {
00306 case GITK_DIALOG_ACCESS_RENDERER: return(gitk_dialog_get_dst(dialog));
00307 case GITK_DIALOG_ACCESS_CLIENT: return(gitk_dialog_get_src(dialog));
00308 }
00309 return(NULL);
00310 }
00311
00312
00319 void gitk_dialog_invalidate(GitkDialogPtr const dialog) {
00320 dialog->changed=TRUE;
00321 if(dialog->dst) {
00322 xmlFreeDoc(dialog->dst);
00323 dialog->dst=NULL;
00324 }
00325 }
00326
00327
00333 static GitkDialogAccessType gitk_toggle_access_type(GitkDialogAccessType access_type) {
00334 return((GitkDialogAccessType)(1-(guint)access_type));
00335 }
00336
00337
00346 void gitk_dialog_set_content(GitkDialogPtr const dialog,GitkDialogAccessType const access_type,xmlXPathCompExprPtr cxpath_expr,gchar * const xpath_expr,const gchar * const new_value) {
00347 xmlNodePtr node;
00348
00349 g_assert(dialog);
00350
00351 gitk_log("gitk_dialog_set_content() beg");
00352
00353
00354 if(!cxpath_expr) {
00355 g_assert(xpath_expr);
00356 cxpath_expr=xmlXPathCompile(xpath_expr);
00357 }
00358
00359 if(cxpath_expr) {
00360
00361 if((node=gitk__cxpath_get_node(dialog,access_type,cxpath_expr,NULL))) {
00362 if(!xmlNodeIsText(node)) {
00363 xmlChar *other_xpath_expr;
00364
00365 if((other_xpath_expr=xmlGetProp(node,"sync"))) {
00366 gitk_log1("[sych] param found : \"%s\"",other_xpath_expr);
00367 cxpath_expr=xmlXPathCompile(other_xpath_expr);
00368 xmlFree(other_xpath_expr);
00369 }
00370
00371 xmlNodeSetContent(node,new_value);
00372 gitk_log("primary content stored");
00373
00374
00375 if((node=gitk__cxpath_get_node(dialog,gitk_toggle_access_type(access_type),cxpath_expr,NULL))) {
00376 if(!xmlNodeIsText(node)) {
00377
00378 xmlNodeSetContent(node,new_value);
00379 gitk_log("secondary content stored");
00380 }
00381 else { gitk_err("unexpected text-node"); }
00382 }
00383 else { gitk_log("failed to get node for xpath expression"); }
00384 }
00385 else { gitk_err("unexpected text-node"); }
00386 }
00387 else { gitk_err("failed to get node for xpath expression"); }
00388 }
00389 else { gitk_err("compiled xpath expr is NULL"); }
00390 gitk_log("gitk_dialog_set_content() end");
00391 }
00392
00393
00402 xmlNodePtr gitk__dialog_get_widget(GitkDialogPtr const dialog,GitkDialogAccessType const access_type,gchar * const widget_id) {
00403 xmlNodePtr node;
00404
00405 g_assert(dialog);
00406 g_assert(widget_id);
00407
00408
00409
00410 node=gitk__xpath_get_node(dialog,access_type,gitk_get_widget_xpath_expression(widget_id),NULL);
00411
00412 return(node);
00413 }
00414
00415
00422 void gitk__dialog_set_title(GitkDialogPtr const dialog,GitkDialogAccessType const access_type,gchar * const new_title) {
00423 g_assert(dialog);
00424 g_assert(new_title);
00425
00426 gitk_log1("gitk_dialog_set_title(\"%s\")",new_title);
00427
00428 gitk_dialog_set_content(dialog,access_type,xpath_get_dialog_name,NULL,new_title);
00429 }
00430
00431
00437 void gitk_dialog_move_focus(GitkWidgetPtr old_widget, GitkWidgetPtr new_widget) {
00438 xmlNodePtr node;
00439
00440 if(old_widget) {
00441 if((node=gitk__dialog_get_widget(old_widget->dialog,GITK_DIALOG_ACCESS_RENDERER,old_widget->id))) {
00442 if(!xmlNodeIsText(node)) xmlSetProp(node,"hasFocus","false");
00443 }
00444 if((node=gitk__dialog_get_widget(old_widget->dialog,GITK_DIALOG_ACCESS_CLIENT,old_widget->id))) {
00445 if(!xmlNodeIsText(node)) xmlSetProp(node,"hasFocus","false");
00446 }
00447 }
00448 if(new_widget) {
00449 if((node=gitk__dialog_get_widget(new_widget->dialog,GITK_DIALOG_ACCESS_RENDERER,new_widget->id))) {
00450 if(!xmlNodeIsText(node)) xmlSetProp(node,"hasFocus","true");
00451 }
00452 if((node=gitk__dialog_get_widget(new_widget->dialog,GITK_DIALOG_ACCESS_CLIENT,new_widget->id))) {
00453 if(!xmlNodeIsText(node)) xmlSetProp(node,"hasFocus","true");
00454 }
00455 }
00456 }
00457