/**
 * create a new action-context, preset with this session's selection
 * @return an action-context. serial is that of the calling session.
 * @param ns    the session
 * @param file  
 */
action_context *action_context_from_selection_(void *ns,const char *file) {
  action_context *ac=NULL,*ss;
  action_file    *af=NULL;
  int             c=0;

  if(!ns||!(ss=noir_sess_get_selection(ns)))
    return NULL;

  if(!file||!action_context_selection_contains(ss,file))
    return NULL;

  if((ac=action_context_new(noir_sess_get_serial(ns),noir_sess_get_cwd(ns)))) {
    if(file&&!(af=action_file_new(NULL,file))) {
      action_context_dst(ac);
      ac=NULL; }
    else {
      ac->single=af;                          /* set single file */
      for(af=ss->selection;af;af=af->next) {  /* set selection */
        c++;
        action_file_new(ac,af->tag); }}}

  ac->flags|=AF_SELECTION; /* we have a selection, flag */
  if(c<=1)
    ac->flags|=AF_LAST;    /* we have just one file, set "last" flag */

  return ac; }



/*****************************************************************************/



#if 0

/**
 * remove 'file' from a session's selection.
 * @param ns - the session, or NULL to remove from all sessions' selections
 * @param file - the file
 */
int selection_remove(noir_sess *ns,char *file) {
  if(ns)
    return action_context_remove_and_dst_file_by_tag(noir_sess_get_selection(ns),file)?NOIR_SUCC:NOIR_NOTFOUND;
  else {
    int ret=NOIR_NOTFOUND;
    for(ns=noir_sess_get_1st();ns;ns=noir_sess_get_next(ns)) {
      if(action_context_remove_and_dst_file_by_tag(noir_sess_get_selection(ns),file))
        ret=NOIR_SUCC; }
    return ret; }}



/**
 * check whether a given session's selection contains a specific file.
 * @return NOIR_SUCC (found), NOIR_NOTFOUND (not found), NOIR_NODATA (no file
 * given), or NOIR_IGNORED (no current selection).
 * @param ns - the session
 * @param file - the file
 */
int selection_contains(noir_sess *ns,const char *file) {
  return action_context_selection_contains(noir_sess_get_selection(ns),file)?NOIR_SUCC:NOIR_NOTFOUND; }

#endif



/*****************************************************************************/



/**
 * set primary selection for session's selection.
 * @param ns - the session to set the primary selection from
 */
static inline int selection_set_primary(noir_sess *ns) {
  char   *p=ns->selection;
  char   *n,*q,*t,*m;
  size_t  l;

  if(p) {
    l=strlen(p);

    while(*p) {
      switch(*p) {
      case '\n': l+=3; break;
      case '\"': l+=2; break;
      default:   l++; }
      p++; }

    if(!(t=m=malloc(l+3))) {
      form_alert(ns,"Cannot set primary selection, out of memory...");
      return NOIR_OOM; }

    p=ns->selection;
    strcpy(t,"\"");

    while(p&&*p) {
      t=strchr(t,'\0');
      q=strchr(p,'\"');
      n=strchr(p,'\n');
      if(!q||(n<q)) {
        if(n) {
          *n='\0';
          strcat(strcpy(t,p),"\" \"");
          *(n++)='\n'; }
        else
          strcpy(t,p);
        p=n; }
      else {
        if(q) {
          *q='\0';
          strcpy(t,p);
          *(q++)='\"';
          *(t++)='\\';
          *(t++)='\"'; }
        else
          strcpy(t,p);
        p=q; }}

    strcat(t,"\"");

    clipboard_set(GDK_SELECTION_PRIMARY,m);

    free(m);

    return NOIR_SUCC; }

  gtk_clipboard_clear(gtk_clipboard_get(GDK_SELECTION_PRIMARY));

  return NOIR_SUCC; }



/*****************************************************************************/



void info_tooltip_show_for(noir_sess *ns,char *file) {
...
  else if(!(fi=file_info_fetch(NULL,file))&&!(fi=find_in_virtual(noir_sess_get_cwd(ns),file))) {
    meta *m=NULL;
    E(0,"no file-info for \"%s\", creating transient meta-data...\n",file);
    if((ret=file_get_meta_only(ns,file,&m))!=NOIR_SUCC) {
      E(0,"file_get_meta_only(%s) failed (1): %d\n",file,ret);
      return; }
    info=meta_to_string(m);
    meta_del_all(&m);
    if(!info)
      return;
    E(3,"file_info_fetch(\"%s\") failed!?\n",file);



/*****************************************************************************/



#if 0
int model_compare(const void *data,const void *pa, const void *pb) {
  return model_sort_fun(*((model_sortflags *)data),
                        ((file_info *)pa)->tag,((file_info *)pa)->intrinsic,
                        ((file_info *)pb)->tag,((file_info *)pb)->intrinsic); }



static inline int model_dir_sort(model_sortflags sort_flags,file_info *dir) {
  int         n=0,c;
  file_info  *fi;
  void      **fb,**fc;

  if(!dir)
    return NOIR_FAIL;
  if(dir->have&FF_SORTED)
    return NOIR_IGNORED;
  if(!(fi=dir->child))
    return NOIR_NODATA;

  do {
    n++;
    fi=fi->next;
  } while(fi);

  if(!(fb=(void **)malloc(sizeof(void *)*n)))
    return NOIR_OOM;

  fc=fb;
  fi=dir->child;
  c=n;

  while(c-->0) {
    *(fc++)=fi;
    fi=fi->next; }

  qsrt(fb,(void *)&sort_flags,0,n-1,model_compare);

  c=n-1;
  fc=fb;
  fi=dir->child=*(fc++);
  while(c-->0) {
    fi->next=*(fc++);
    fi=fi->next; }
  fi->next=NULL;

  free(fb);

  dir->have|=FF_SORTED;

  return NOIR_SUCC; }
#endif






/*****************************************************************************/
/* evas-buffer */



#if 0
#ifdef HAVE_EVAS_BUFFER
#  include "Evas_Engine_Buffer.h"
#endif



int evas_buffer(Evas **evas_r,char **buf_r,int w,int h) {
#ifndef HAVE_EVAS_BUFFER
  int ret=NOIR_IGNORED;
  if(evas_r) *evas_r=NULL;
  if(buf_r)  *buf_r=NULL;
#else
  unsigned char           *buf=NULL;
  Evas_Engine_Info_Buffer *einfo;
  Evas                    *evas;
  int                      rm,ret=NOIR_SUCC;

  if(!evas_r||!buf_r)
    return NOIR_FAIL;

  if((rm=evas_render_method_lookup("buffer"))!=RENDER_METHOD_INVALID) {
    E(0,"(%d,%d): cannot look up the \"buffer\" render method...\n",w,h);
    return NOIR_NOTFOUND; }

  if(!(evas=evas_new())) {
    E(0,"(%d,%d): cannot create evas!?\n",w,h);
    return NOIR_OOM; }

  evas_output_method_set(evas,rm);
  evas_output_size_set(evas,w,h);
  evas_output_viewport_set(evas,0,0,w,h);

  if((einfo=(Evas_Engine_Info_Buffer *)evas_engine_info_get(evas))) {
    einfo->info.depth_type=EVAS_ENGINE_BUFFER_DEPTH_BGR24;
    if((buf=malloc(w*h*3))) {
      einfo->info.dest_buffer=buf;
      einfo->info.dest_buffer_row_bytes=w*3;
      einfo->info.use_color_key=1;
      einfo->info.alpha_threshold=128;
      einfo->info.color_key_r=0xff;
      einfo->info.color_key_g=0x00;
      einfo->info.color_key_b=0xff;
      evas_engine_info_set(evas,(Evas_Engine_Info *)einfo); }
    else {
      E(0,"(%d,%d): cannot allocate buffer!?\n",w,h);
      ret=NOIR_OOM; }}
  else
    ret=NOIR_NODATA;

  if(!buf) {                /* something went wrong */
    if(einfo)
      einfo=NULL;
    evas_free(evas);
    evas=NULL; }

  *buf_r=buf;
  *evas_r=evas;
#endif
  return ret; }
#endif



/*****************************************************************************/



/*****************************************************************************/
