/* * $Id: kbrow.c,v 1.1.1.1 1996/03/08 15:32:52 mclareni Exp $ * * $Log: kbrow.c,v $ * Revision 1.1.1.1 1996/03/08 15:32:52 mclareni * Kuip * */ /*CMZ : 2.07/06 14/06/95 15.23.02 by Gunter Folger*/ /*-- Author : Alfred Nathaniel 07/08/92*/ /* kbrow.c */ #include "kuip/kuip.h" #include "kuip/kfor.h" #include "kuip/kbrow.h" #include "kuip/klink.h" #include "kuip/kmenu.h" #include "kuip/kflag.h" #include "kuip/ksig.h" EXTERN char cdf_def[80], cdf_value[80]; static KmClass *kmclasses; /* list of object classes */ static BrObject *brobjects; /* list of browsable objects */ /* internal functions */ static void decode_setting( BrObject*, const char* ); static BrClass* find_brclass( const char* ); static KmObject* find_kmobject( const char* ); static BrVariable* find_variable( BrObject*, const char* ); static void free_variables( BrVariable* ); /* * add to the list of browsable classes */ void klnkbrcl( BrClass *brcls_list, int version ) { BrClass *brcls; strcpy ( cdf_def, "Browser Class" ); strcpy ( cdf_value, brcls_list->name ); check_version( version, KUIP_VERSION ); /* fill the reference to the class structure in the open action */ for( brcls = brcls_list; brcls != NULL; brcls = brcls->next ) { BrAction *bract; for( bract = brcls->open; bract != NULL; bract = bract->next ) bract->class = brcls; } if( brclasses == NULL ) brclasses = brcls_list; else { for( brcls = brclasses; brcls->next != NULL; ) brcls = brcls->next; brcls->next = brcls_list; } } /* * add to the list of object classes */ void klnkkmcl( KmClass *kmcls_list, int version ) { strcpy ( cdf_def, "Object Class" ); strcpy ( cdf_value, kmcls_list->name ); check_version( version, KUIP_VERSION ); if( kmclasses == NULL ) kmclasses = kmcls_list; else { KmClass *kmcls = kmclasses; while( kmcls != NULL ) { /* redefinition of class name ? */ if( strcasecmp( kmcls->name, kmcls_list->name ) == 0 ) { /* copy new attributes */ if( kmcls_list->title != NULL ) kmcls->title = kmcls_list->title; if( kmcls_list->big_icon != NULL ) kmcls->big_icon = kmcls_list->big_icon; if( kmcls_list->sm_icon != NULL ) kmcls->sm_icon = kmcls_list->sm_icon; if( kmcls_list->user_icon_F != NULL ) kmcls->user_icon_F = kmcls_list->user_icon_F; if( kmcls_list->user_icon_C != NULL ) kmcls->user_icon_C = kmcls_list->user_icon_C; /* append actions */ if( kmcls->cont == NULL ) kmcls->cont = kmcls_list->cont; else if( kmcls_list->cont != NULL ) { BrAction *bract = kmcls->cont; while( bract->next != NULL ) bract = bract->next; bract->next = kmcls_list->cont; } if( kmcls->graf == NULL ) kmcls->graf = kmcls_list->graf; else if( kmcls_list->graf != NULL ) { BrAction *bract = kmcls->graf; while( bract->next != NULL ) bract = bract->next; bract->next = kmcls_list->graf; } if( kmcls_list->next != NULL ) klnkkmcl( kmcls_list->next, version ); return; } else if( kmcls->next == NULL ) { /* append new class name at end of list */ kmcls->next = kmcls_list; if( kmcls_list->next != NULL ) { KmClass *next = kmcls_list->next; kmcls_list->next = NULL; klnkkmcl( next, version ); } return; } else kmcls = kmcls->next; } } } /* * add to the list of buttons */ void klnkbutt( KmButton *kmbut_list, int version ) { if (kmbut_list->menu != NULL) { strcpy ( cdf_def, "Menu" ); strcpy ( cdf_value, kmbut_list->menu ); } else { strcpy ( cdf_def, "Button" ); strcpy ( cdf_value, kmbut_list->label ); } check_version( version, KUIP_VERSION ); if( kmbuttons == NULL ) kmbuttons = kmbut_list; else { KmButton *kmbut = kmbuttons; while( kmbut->next != NULL ) kmbut = kmbut->next; kmbut->next = kmbut_list; } } /* * return widget ID for a button */ KmWidget find_button( const char *label, const char *menu ) { KmButton *kmbut; if( menu == NULL ) { /* search for button */ for( kmbut = kmbuttons; kmbut != NULL; kmbut = kmbut->next ) { if( kmbut->menu == NULL && strcasecmp( kmbut->label, label ) == 0 ) return kmbut->widget; } } else { /* search for menu item */ for( kmbut = kmbuttons; kmbut != NULL; kmbut = kmbut->next ) { if( kmbut->menu != NULL && strcasecmp( kmbut->menu, menu ) == 0 && strcasecmp( kmbut->label, label ) == 0 ) return kmbut->widget; } } return (KmWidget)0; } /* * perform the action */ void exec_action( BrAction *bract, const char *brobj_name, const char *kmobj_name, int force_panel, KmWidget widget, KmCalldata calldata ) { kc_break.intr_pending = 0; if( bract == NULL ) return; if( bract->exec != NULL ) { int status; int want_prompt = force_panel ? -1 : 1; char cmd[256]; char *s, *p; int n; for( s = bract->exec, n = 0; *s != '\0' && n < (sizeof cmd) - 1; ) { if( *s == '[' ) { /* variable substitution */ if( (p = strchr( s, ']' )) != NULL ) { int len = p - s - 1; char *var = strndup( s + 1, len ); const char *val = NULL; int lval = 0; if( bract->tag == BRACT_GRAF ) { /* * in the graf window kmobj_name contains the comma separated * list of the object hierarchy returned by IGOBJ * "this" refers to the lowest level * "this1", "this2", ... refer to the higher levels */ if( strcasecmp( var, "this" ) == 0 || ( len == 5 && isdigit( var[4] ) && strncasecmp( var, "this", 4 ) == 0 ) ) { int k; for( k = (len == 4) ? 0 : atoi( &var[4] ), val = kmobj_name; k > 0 && val != NULL; k-- ) { val = strchr( val, ',' ); if( val != NULL ) val++; } if( val != NULL ) { const char *comma = strchr( val, ',' ); if( comma != NULL ) lval = comma - val; } } } else if( strcasecmp( var, "this" ) == 0 ) val = kmobj_name; else if( bract->tag == BRACT_CONT && strcasecmp( var, "that" ) == 0 ) { /* "that" is replaced by the short text used as alias name */ KmObject *kmobj = find_kmobject( kmobj_name ); if( kmobj != NULL ) val = kmobj->stext; } else if( brobj_name != NULL ) val = get_variable( brobj_name, var ); free( var ); if( val != NULL ) { int quote = 0; if( lval == 0 ) { lval = strlen( val ); quote = (strchr( val, ' ' ) != NULL); } if( quote ) cmd[n++] = '\''; strncpy( &cmd[n], val, lval ); n += lval; if( quote ) cmd[n++] = '\''; s = p + 1; continue; } } } cmd[n++] = *s++; } cmd[n] = '\0'; if( kc_flags.echo_command > 0 ) printf( "%s> %s\n", kc_flags.echo_prompt, cmd ); status = exec_cmd_string( cmd, want_prompt, kjmpaddr.disp_panel_C ); if( status == KUMAC_UNWIND ) return; /* do not go into callback function */ } if( bract->call_F != NULL || bract->call_C != NULL ) { BrObject *brobj; BrClass *brcls; char *brcls_name; char *path; KmClass *kmcls; const char *kmcls_name; KmObject *kmobj; char *short_text; char *long_text; BrClientdata clientdata; if( bract->call_C != NULL ) { clientdata.tag = bract->tag; clientdata.brobj = NULL; clientdata.brcls = NULL; clientdata.path = NULL; clientdata.kmobj = NULL; clientdata.kmcls = NULL; clientdata.stext = NULL; clientdata.ltext = NULL; clientdata.mtext = bract->text; } switch( bract->tag ) { case BRACT_OPEN: brcls_name = bract->class->name; if( bract->call_F != NULL ) { int lbrcls_name = strlen( brcls_name ); F77_CALL_C(bract->call_F,brcls_name,lbrcls_name); } else if( bract->call_C != NULL ) { clientdata.brcls = brcls_name; (*bract->call_C)(widget,&clientdata,calldata); } break; case BRACT_ROOT: brobj = find_brobject( brobj_name ); brcls = brobj->class; brcls_name = brcls->name; path = get_variable( brobj_name, "path" ); if( bract->call_F != NULL ) { int lbrobj_name = strlen( brobj_name ); int lbrcls_name = strlen( brcls_name ); int lpath = strlen( path ); F77_CALL_C3(bract->call_F,brobj_name,lbrobj_name, brcls_name,lbrcls_name,path,lpath); } else if( bract->call_C != NULL ) { clientdata.brobj = brobj_name; clientdata.brcls = brcls_name; clientdata.path = path; (*bract->call_C)(widget,&clientdata,calldata); } break; case BRACT_CONT: brobj = find_brobject( brobj_name ); brcls = brobj->class; brcls_name = brcls->name; path = get_variable( brobj_name, "path" ); kmobj = find_kmobject( kmobj_name ); kmcls = kmobj->class; kmcls_name = kmcls->name; short_text = kmobj->stext; long_text = kmobj->ltext; if( bract->call_F != NULL ) { int lbrobj_name = strlen( brobj_name ); int lbrcls_name = strlen( brcls_name ); int lpath = strlen( path ); int lkmobj_name = strlen( kmobj_name ); int lkmcls_name = strlen( kmcls_name ); int lshort_text; int llong_text; if( short_text == NULL ) short_text = " "; lshort_text = strlen( short_text ); if( long_text == NULL ) long_text = " "; llong_text = strlen( long_text ); F77_CALL_C7(bract->call_F,brobj_name,lbrobj_name, brcls_name,lbrcls_name,path,lpath, kmobj_name,lkmobj_name,kmcls_name,lkmcls_name, short_text,lshort_text,long_text,llong_text); } else if( bract->call_C != NULL ) { clientdata.brobj = brobj_name; clientdata.brcls = brcls_name; clientdata.path = path; clientdata.kmobj = kmobj_name; clientdata.kmcls = kmcls_name; clientdata.stext = short_text; clientdata.ltext = long_text; (*bract->call_C)(widget,&clientdata,calldata); } break; case BRACT_GRAF: kmcls_name = brobj_name; /* special !!! */ if( bract->call_F != NULL ) { int lkmobj_name = strlen( kmobj_name ); int lkmcls_name = strlen( kmcls_name ); F77_CALL_CC(bract->call_F,kmobj_name,lkmobj_name, kmcls_name,lkmcls_name); } else if( bract->call_C != NULL ) { clientdata.kmobj = kmobj_name; clientdata.kmcls = kmcls_name; (*bract->call_C)(widget,&clientdata,calldata); } break; } } } /* * find action structure with given menu text * * if user_text == NULL leave it unchanged * if user_text == "" revert to CDF text * otherwise set new user text * * if sensitive|toggle_on < 0 leave it unchanges * otherwise set new value * * return -1 if structure not found * otherwise return present sensitivity and toggle state */ int set_action( const char *class_name, int is_browsable, /* select object or browsable class */ int graf_or_open, /* select CONT/GRAF or ROOT/OPEN */ const char *text, const char *user_text, int sensitive, int toggle_on ) { BrAction *bract = NULL; int states = -1; if( is_browsable ) { BrClass *brcls = find_brclass( class_name ); if( brcls != NULL ) bract = graf_or_open ? brcls->open : brcls->root; } else { KmClass *kmcls = find_kmclass( class_name ); if( kmcls != NULL ) bract = graf_or_open ? kmcls->graf : kmcls->cont; } for( ; bract != NULL; bract = bract->next ) { if( strcasecmp( bract->text, text ) == 0 ) { /* prepare the return value of present states */ states = 0; if( bract->flags & BrActSensitive ) states |= 1; if( bract->flags & BrActToggleOn ) states |= 2; if( sensitive >= 0 ) { bract->flags &= ~BrActSensitive; if( sensitive ) bract->flags |= BrActSensitive; } if( toggle_on >= 0 ) { bract->flags &= ~BrActToggleOn; if( toggle_on ) bract->flags |= BrActToggleOn; } if( user_text != NULL ) { if( bract->user_text != NULL ) free( bract->user_text ); bract->user_text = str0dup( user_text ); } break; } } return states; } /* * build the list of all browsable objects to be displayed in the root window */ BrObject *scan_brobjects() { BrObject *save_brobjects = brobjects; BrObject *brobj = NULL; BrClass *brcls; brobjects = NULL; /* scan through the list of browsable classes */ for( brcls = brclasses; brcls != NULL; brcls = brcls->next ) { char *root; if( brcls->scan_br_F == NULL && brcls->scan_br_C == NULL ) { /* no scan function --> only one object with name = class name */ if( brobjects == NULL ) brobj = brobjects = (BrObject*)malloc( sizeof(BrObject) ); else brobj = brobj->next = (BrObject*)malloc( sizeof(BrObject) ); brobj->next = NULL; brobj->name = strdup( brcls->name ); brobj->class = brcls; brobj->vars = NULL; set_variable( brobj, "name", brobj->name ); } else { /* call the user scan function to retrieve the list of browsables */ char *brcls_name = brcls->name; int lbrcls_name = strlen( brcls_name ); char brobj_name[32]; int lbrobj_name = (sizeof brobj_name); char brvar_set[256]; int lbrvar_set = (sizeof brvar_set); int first_call = 1; memset( brobj_name, ' ', lbrobj_name ); while( 1 ) { char *name; char *vars; if( brcls->scan_br_F != NULL ) { memset( brvar_set, ' ', lbrvar_set ); F77_CALL_C3(brcls->scan_br_F,brcls_name,lbrcls_name, brobj_name,lbrobj_name,brvar_set,lbrvar_set); name = fstr0trim( brobj_name, lbrobj_name ); if( name == NULL ) break; /* empty object name flags end of list */ vars = fstr0dup( brvar_set, lbrvar_set ); } else { char **brobj_dsc = (*brcls->scan_br_C)( brcls->name, first_call ); if( brobj_dsc == NULL ) break; first_call = 0; name = str0dup( brobj_dsc[0] ); if( name == NULL ) break; vars = str0dup( brobj_dsc[1] ); } if( brobjects == NULL ) brobj = brobjects = (BrObject*)malloc( sizeof(BrObject) ); else brobj = brobj->next = (BrObject*)malloc( sizeof(BrObject) ); brobj->next = NULL; brobj->name = name; brobj->class = brcls; brobj->vars = NULL; set_variable( brobj, "name", brobj->name ); root = str2dup( "//", brobj->name ); set_variable( brobj, "root", root ); free( root ); if( vars != NULL ) { decode_setting( brobj, vars ); free( vars ); } } } } for( brobj = save_brobjects; brobj != NULL; ) { /* free allocated space in the previous list of browsable objects */ BrObject *next = brobj->next; BrObject *new_brobj = find_brobject( brobj->name ); if( new_brobj != NULL ) { /* restore previous variable settings */ BrVariable *brvar; for( brvar = brobj->vars; brvar != NULL; brvar = brvar->next ) { BrVariable *new_brvar = find_variable( new_brobj, brvar->name ); if( new_brvar == NULL ) set_variable( new_brobj, brvar->name, brvar->value ); } } free_variables( brobj->vars ); free( brobj->name ); free( brobj ); brobj = next; } return brobjects; } /* * build the list of all objects to be displayed in the content window */ KmObject *scan_kmobjects( const char *brobj_name, const char *path_name, int browser_number ) { static char dummy_path[] = "//..."; static int ldummy_path = (sizeof dummy_path) - 1; int lbrobj_name = strlen( brobj_name ); const char *path = path_name; int lpath; char kmobj_name[32]; int lkmobj_name = (sizeof kmobj_name); char kmcls_name[32]; int lkmcls_name = (sizeof kmcls_name); char short_text[80]; int lshort_text = (sizeof short_text); char long_text[80]; int llong_text = (sizeof long_text); char *brcls_name; int lbrcls_name; BrObject *brobj = find_brobject( brobj_name ); KmObject *kmobj; KmClass *kmcls; char path_n[16]; int i; if( brobj == NULL ) { printf( "scan_kmobjects: browsable object %s not found\n", brobj_name ); return NULL; } brcls_name = brobj->class->name; lbrcls_name = strlen( brcls_name ); if( strncmp( path_name, dummy_path, ldummy_path ) == 0 ) { /* ignore the dummy path header */ path = path_name + ldummy_path; } lpath = strlen( path ); set_variable( brobj, "path", path ); /* remember the last path setting in each browser */ sprintf( path_n, "path_%d", browser_number ); set_variable( brobj, path_n, path ); /* reset the object counters in the class structure used for "summary" */ for( kmcls = kmclasses; kmcls != NULL; kmcls = kmcls->next ) kmcls->obj_count = 0; /* free allocated space in the existing list of objects */ for( kmobj = kmobjects; kmobj != NULL; ) { KmObject *next = kmobj->next; free( kmobj->name ); if( kmobj->stext != NULL ) free( kmobj->stext ); if( kmobj->ltext != NULL ) free( kmobj->ltext ); free( kmobj ); kmobj = next; } kmobjects = NULL; /* call the user scan function to retrieve the list of objects */ /* * SUBROUTINE scan_km(BRNAME,BRCLASS,PATH,OBJNAME,KMCLASS,STEXT,LTEXT) * CHARACTER*(*) BRCLASS,BRNAME,PATH,OBJNAME,KMCLASS,STEXT,LTEXT * * input BRNAME : name of the browsable object, e.g. 'LUN1' * input BRCLASS : class name of the browsable object, e.g. 'HBOOK' * input PATH : path of selected directory, e.g '//LUN1' or '//LUN1/DIR' * in/out OBJNAME : name of the next object * output KMCLASS : class name of the object * output STEXT : short text describing the object * output LTEXT : long text describing the object * * If called with OBJNAME=' ' this routine has to return the first object * in the current directory of the browsable object BRNAME. Otherwise it has * to return the next object. If there is no next object it has to return * OBJNAME=' '. * * * SUBROUTINE scan_br(BRCLASS,BRNAME,VARSET) * CHARACTER*(*) BRCLASS,BRNAME,VARSET * */ for( i = 0; 1; i++ ) { char *oname = NULL; char *cname = NULL; char *stext = NULL; char *ltext = NULL; if( brobj->class->scan_km_F != NULL ) { if( i == 0 ) memset( kmobj_name, ' ', lkmobj_name ); memset( short_text, ' ', lshort_text ); memset( long_text, ' ', llong_text ); F77_CALL_C7(brobj->class->scan_km_F, brobj_name,lbrobj_name,brcls_name,lbrcls_name,path,lpath, kmobj_name,lkmobj_name,kmcls_name,lkmcls_name, short_text,lshort_text,long_text,llong_text); oname = fstr0trim( kmobj_name, lkmobj_name ); cname = fstr0trim( kmcls_name, lkmcls_name ); stext = fstr0trim( short_text, lshort_text ); ltext = fstr0dup( long_text, llong_text ); } else { char **obj_desc = (*brobj->class->scan_km_C)( brobj_name, brcls_name, path, i ); if( obj_desc != NULL ) { oname = str0dup( obj_desc[0] ); cname = str0dup( obj_desc[1] ); stext = str0dup( obj_desc[2] ); ltext = str0dup( obj_desc[3] ); } } if( oname == NULL ) { if( ltext == NULL ) { /* construct summary from object count in class structure */ int len = 0; ltext = malloc( 1 ); ltext[0] = '\0'; for( kmcls = kmclasses; kmcls != NULL; kmcls = kmcls->next ) { if( kmcls->obj_count != 0 ) { char *sp1 = len > 0 ? " " : ""; int nsp1 = strlen( sp1 ); char *txt = kmcls->title; int ntxt = strlen( txt ); char *sp2 = " : "; int nsp2 = strlen( sp2 ); char cnt[32]; int ncnt; sprintf( cnt, "%d", kmcls->obj_count ); ncnt = strlen( cnt ); ltext = realloc( ltext, len + nsp1 + ntxt + nsp2 + ncnt + 1 ); strcpy( <ext[len], sp1 ); len += nsp1; strcpy( <ext[len], txt ); len += ntxt; strcpy( <ext[len], sp2 ); len += nsp2; strcpy( <ext[len], cnt ); len += ncnt; } } } set_variable( brobj, "summary", ltext ); free( ltext ); break; /* empty object name flags end of list */ } if( kmobjects == NULL ) kmobj = kmobjects = (KmObject*)malloc( sizeof(KmObject) ); else kmobj = kmobj->next = (KmObject*)malloc( sizeof(KmObject) ); kmobj->next = NULL; kmobj->name = oname; kmobj->stext = stext; kmobj->ltext = ltext; if( (kmobj->class = find_kmclass( cname )) == NULL ) { printf( " *** Invalid class name %s\n", cname ); } else if( strcasecmp( kmobj->class->name, "DirUpFile" ) != 0 ) { kmobj->class->obj_count++; /* summary count */ } free( cname ); } return kmobjects; } /* * return the value of variable or NULL if name not found */ char *get_variable( const char *brobj_name, const char *brvar_name ) { BrObject *brobj = find_brobject( brobj_name ); BrVariable *brvar = find_variable( brobj, brvar_name ); if( brvar == NULL ) return NULL; return brvar->value; } /* * return pointer to browsable class structure or NULL if name not found */ static BrClass *find_brclass( const char *brcls_name ) { BrClass *brcls; for( brcls = brclasses; brcls != NULL; brcls = brcls->next ) if( strcasecmp( brcls->name, brcls_name ) == 0 ) break; return brcls; } /* * return pointer to browsable object structure or NULL if name not found */ BrObject *find_brobject( const char *brobj_name ) { BrObject *brobj; for( brobj = brobjects; brobj != NULL; brobj = brobj->next ) if( strcasecmp( brobj->name, brobj_name ) == 0 ) break; return brobj; } /* * return pointer to object class structure or NULL if name not found */ KmClass *find_kmclass( const char *kmcls_name ) { KmClass *kmcls; for( kmcls = kmclasses; kmcls != NULL; kmcls = kmcls->next ) if( strcasecmp( kmcls->name, kmcls_name ) == 0 ) break; return kmcls; } /* * return pointer to object structure or NULL if name not found */ static KmObject *find_kmobject( const char *kmobj_name ) { KmObject *kmobj; for( kmobj = kmobjects; kmobj != NULL; kmobj = kmobj->next ) if( strcasecmp( kmobj->name, kmobj_name ) == 0 ) break; return kmobj; } /* * return pointer to variable structure or NULL if name not found */ static BrVariable *find_variable( BrObject *brobj, const char *brvar_name ) { BrVariable *brvar; for( brvar = brobj->vars; brvar != NULL; brvar = brvar->next ) if( strcasecmp( brvar->name, brvar_name ) == 0 ) break; return brvar; } /* * free the space allocated for a variable list */ static void free_variables( BrVariable *brvar ) { while( brvar != NULL ) { BrVariable *next = brvar->next; free( brvar->name ); free( brvar->value ); free( brvar ); brvar = next; } } /* * set the variable name to value */ void set_variable( BrObject *brobj, const char *brvar_name, const char *brvar_value ) { BrVariable *brvar = find_variable( brobj, brvar_name ); if( brvar == NULL ) { /* allocate a new variable */ if( brobj->vars == NULL ) brvar = brobj->vars = (BrVariable*)malloc( sizeof(BrVariable) ); else { for( brvar = brobj->vars; brvar->next != NULL; brvar = brvar->next ) ; brvar = brvar->next = (BrVariable*)malloc( sizeof(BrVariable) ); } brvar->next = NULL; brvar->name = strdup( brvar_name ); } else if( brvar->value != NULL ) /* change value of existing variable */ free( brvar->value ); if( brvar_value == NULL ) brvar->value = NULL; else brvar->value = strdup( brvar_value ); } /* * decode blank separated variable settings "name1=value1 name2=value2 ..." * single quotes can be used to include blanks */ static void decode_setting( BrObject *brobj, const char *brvar_set ) { char *line = strdup( brvar_set ); /* make a local copy for strqtok() */ char *p; char *name; for( name = strqtok( line ); name != NULL; name = strqtok( NULL ) ) { /* name points to the next "name=value" */ char *value; name = strdup( name ); if( (value = strchr( name, '=' )) != NULL ) { *value++ = '\0'; /* name points to "name" and value points to "value" */ if( *value == '\'' ) { /* remove quotes */ if( (p = strrchr( ++value, '\'' )) != NULL ) *p = '\0'; } set_variable( brobj, name, value ); } free( name ); } free( line ); }