static gboolean
pp_jobs_dialog_free_idle (gpointer user_data)
{
  PpJobsDialog *dialog = (PpJobsDialog*) user_data;

  if (dialog->ref_count == 0)
    {
      gtk_widget_destroy (GTK_WIDGET (dialog->dialog));
      dialog->dialog = NULL;

      g_object_unref (dialog->builder);
      dialog->builder = NULL;

      if (dialog->num_jobs > 0)
        cupsFreeJobs (dialog->num_jobs, dialog->jobs);

      g_free (dialog->printer_name);

      g_free (dialog);

      return FALSE;
    }
  else
    {
      return TRUE;
    }
}
Exemplo n.º 2
0
/*
* call-seq:
*   Cups.all_jobs(printer) -> Hash
*
* Get all jobs from default CUPS server. Takes a single printer/class string argument.
* Returned hash keys are CUPS job ids, and the values are hashes of job info
* with keys:
*
* [:title, :submitted_by, :size, :format, :state]
*/
static VALUE cups_get_jobs(VALUE self, VALUE printer)
{
    VALUE job_list, job_info_hash, jid, jtitle, juser, jsize, jformat, jstate;
    int job_id;
    int num_jobs;
    cups_job_t *jobs;
    ipp_jstate_t state;
    int i;
    char *printer_arg = RSTRING_PTR(printer);

    num_jobs = cupsGetJobs(&jobs, printer_arg, 1, -1); // Get jobs
    job_list = rb_hash_new();

    for (i = 0; i < num_jobs; i ++) { // Construct a hash of individual job info
        job_info_hash = rb_hash_new();
        jid = INT2NUM(jobs[i].id);
        jtitle = rb_str_new2(jobs[i].title);
        juser = rb_str_new2(jobs[i].user);
        jsize = INT2NUM(jobs[i].size);
        jformat = rb_str_new2(jobs[i].format);

        // Let's elaborate on that job state...
        switch (jobs[i].state) {
        case IPP_JOB_PENDING :
            jstate = rb_str_new2("Pending...");
            break;
        case IPP_JOB_HELD :
            jstate = rb_str_new2("Held");
            break;
        case IPP_JOB_PROCESSING :
            jstate = rb_str_new2("Processing...");
            break;
        case IPP_JOB_STOPPED :
            jstate = rb_str_new2("Stopped");
            break;
        case IPP_JOB_CANCELED :
            jstate = rb_str_new2("Cancelled");
            break;
        case IPP_JOB_ABORTED :
            jstate = rb_str_new2("Aborted");
            break;
        case IPP_JOB_COMPLETED :
            jstate = rb_str_new2("Completed");
        }

        rb_hash_aset(job_info_hash, ID2SYM(rb_intern("title")), jtitle);
        rb_hash_aset(job_info_hash, ID2SYM(rb_intern("submitted_by")), juser);
        rb_hash_aset(job_info_hash, ID2SYM(rb_intern("size")), jsize);
        rb_hash_aset(job_info_hash, ID2SYM(rb_intern("format")), jformat);
        rb_hash_aset(job_info_hash, ID2SYM(rb_intern("state")), jstate);

        rb_hash_aset(job_list, jid, job_info_hash); // And push it all into job_list hash
    }

    // Free job array
    cupsFreeJobs(num_jobs, jobs);

    return job_list;
}
Exemplo n.º 3
0
/*
* call-seq:
*   print_job.state -> String
*
* Get human-readable state of current job.
*/
static VALUE cups_get_job_state(VALUE self)
{
    VALUE job_id = rb_iv_get(self, "@job_id");
    VALUE printer = rb_iv_get(self, "@printer");
    VALUE jstate;

    int num_jobs;
    cups_job_t *jobs;
    ipp_jstate_t job_state = IPP_JOB_PENDING;
    int i;
    char *printer_arg = RSTRING_PTR(printer);

    if (NIL_P(job_id)) {
        return Qnil;
    } else {
        num_jobs = cupsGetJobs(&jobs, printer_arg, 1, -1); // Get jobs

        for (i = 0; i < num_jobs; i ++) {
            if (jobs[i].id == NUM2INT(job_id)) {
                job_state = jobs[i].state;
                break;
            }
        }

        // Free job array
        cupsFreeJobs(num_jobs, jobs);

        switch (job_state) {
        case IPP_JOB_PENDING :
            jstate = rb_str_new2("Pending...");
            break;
        case IPP_JOB_HELD :
            jstate = rb_str_new2("Held");
            break;
        case IPP_JOB_PROCESSING :
            jstate = rb_str_new2("Processing...");
            break;
        case IPP_JOB_STOPPED :
            jstate = rb_str_new2("Stopped");
            break;
        case IPP_JOB_CANCELED :
            jstate = rb_str_new2("Cancelled");
            break;
        case IPP_JOB_ABORTED :
            jstate = rb_str_new2("Aborted");
            break;
        case IPP_JOB_COMPLETED :
            jstate = rb_str_new2("Completed");
            break;
        default:
            jstate = rb_str_new2("Unknown Job Code...");
        }

        return jstate;
    }
}
Exemplo n.º 4
0
void ofxCUPS::checkActiveJobStatus()
{  
    
    //cups_dest_t *dest;  
    cups_job_t *jobs;  
    string info;
    
    /* Get my jobs (1) with any state (-1) */  
    int num_jobs = cupsGetJobs(&jobs, printerName.c_str(), 0, CUPS_WHICHJOBS_ACTIVE);  
    cout << "there are " << num_jobs << " active jobs." << endl;
    
    
    
    for (int i = 0; i < num_jobs; i ++)
    { 
        ipp_jstate_t job_state = jobs[i].state;  
        switch (job_state)  
        {  
            case IPP_JOB_PENDING :  
                info += "Job " + ofToString(jobs[i].id) + " is pending.\n";  
                break;  
            case IPP_JOB_HELD :  
                info += "Job " + ofToString(jobs[i].id) + " is held.\n";  
                break;  
            case IPP_JOB_PROCESSING :  
                info += "Job " + ofToString(jobs[i].id) + " is processing.\n";  
                break;  
            case IPP_JOB_STOPPED :  
                info += "Job " + ofToString(jobs[i].id) + " is stopped.\n";  
                break;  
            case IPP_JOB_CANCELED :  
                info += "Job " + ofToString(jobs[i].id) + " is pending.\n";  
                break;  
            case IPP_JOB_ABORTED :  
                info += "Job " + ofToString(jobs[i].id) + " is aborted.\n";  
                break;  
            case IPP_JOB_COMPLETED :  
                info += "Job " + ofToString(jobs[i].id) + " is completed.\n";  
                break;  
        }
    }
    cout << info << endl;
    cupsFreeJobs(num_jobs, jobs);
}
Exemplo n.º 5
0
/*
* call-seq:
*   print_job.completed? -> true or false
*
* Has the job completed?
*/
static VALUE cups_job_completed(VALUE self)
{
    VALUE job_id = rb_iv_get(self, "@job_id");
    VALUE printer = rb_iv_get(self, "@printer");
    VALUE jstate;

    int num_jobs;
    cups_job_t *jobs;
    ipp_jstate_t job_state = IPP_JOB_PENDING;
    int i;
    char *printer_arg = RSTRING_PTR(printer);

    if (NIL_P(job_id)) {
        return Qfalse;
    } else {
        num_jobs = cupsGetJobs(&jobs, printer_arg, 1, -1); // Get jobs
        // job_state = IPP_JOB_COMPLETED;

        for (i = 0; i < num_jobs; i ++) {
            if (jobs[i].id == NUM2INT(job_id)) {
                job_state = jobs[i].state;
                break;
            }

            // Free job array
            cupsFreeJobs(num_jobs, jobs);

            if (job_state == IPP_JOB_COMPLETED) {
                return Qtrue;
            } else {
                return Qfalse;
            }

        }
    }
}
Exemplo n.º 6
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		status = 0,		/* Exit status */
		i,			/* Looping var */
		num_dests;		/* Number of destinations */
  cups_dest_t	*dests,			/* Destinations */
		*dest,			/* Current destination */
		*named_dest;		/* Current named destination */
  const char	*ppdfile;		/* PPD file */
  ppd_file_t	*ppd;			/* PPD file data */
  int		num_jobs;		/* Number of jobs for queue */
  cups_job_t	*jobs;			/* Jobs for queue */


  if (argc > 1)
  {
    if (!strcmp(argv[1], "enum"))
    {
      cups_ptype_t	mask = CUPS_PRINTER_LOCAL,
					/* Printer type mask */
			type = CUPS_PRINTER_LOCAL;
					/* Printer type */
      int		msec = 0;	/* Timeout in milliseconds */


      for (i = 2; i < argc; i ++)
        if (isdigit(argv[i][0] & 255) || argv[i][0] == '.')
          msec = (int)(atof(argv[i]) * 1000);
        else if (!_cups_strcasecmp(argv[i], "bw"))
        {
          mask |= CUPS_PRINTER_BW;
          type |= CUPS_PRINTER_BW;
        }
        else if (!_cups_strcasecmp(argv[i], "color"))
        {
          mask |= CUPS_PRINTER_COLOR;
          type |= CUPS_PRINTER_COLOR;
        }
        else if (!_cups_strcasecmp(argv[i], "mono"))
        {
          mask |= CUPS_PRINTER_COLOR;
        }
        else if (!_cups_strcasecmp(argv[i], "duplex"))
        {
          mask |= CUPS_PRINTER_DUPLEX;
          type |= CUPS_PRINTER_DUPLEX;
        }
        else if (!_cups_strcasecmp(argv[i], "simplex"))
        {
          mask |= CUPS_PRINTER_DUPLEX;
        }
        else if (!_cups_strcasecmp(argv[i], "staple"))
        {
          mask |= CUPS_PRINTER_STAPLE;
          type |= CUPS_PRINTER_STAPLE;
        }
        else if (!_cups_strcasecmp(argv[i], "copies"))
        {
          mask |= CUPS_PRINTER_COPIES;
          type |= CUPS_PRINTER_COPIES;
        }
        else if (!_cups_strcasecmp(argv[i], "collate"))
        {
          mask |= CUPS_PRINTER_COLLATE;
          type |= CUPS_PRINTER_COLLATE;
        }
        else if (!_cups_strcasecmp(argv[i], "punch"))
        {
          mask |= CUPS_PRINTER_PUNCH;
          type |= CUPS_PRINTER_PUNCH;
        }
        else if (!_cups_strcasecmp(argv[i], "cover"))
        {
          mask |= CUPS_PRINTER_COVER;
          type |= CUPS_PRINTER_COVER;
        }
        else if (!_cups_strcasecmp(argv[i], "bind"))
        {
          mask |= CUPS_PRINTER_BIND;
          type |= CUPS_PRINTER_BIND;
        }
        else if (!_cups_strcasecmp(argv[i], "sort"))
        {
          mask |= CUPS_PRINTER_SORT;
          type |= CUPS_PRINTER_SORT;
        }
        else if (!_cups_strcasecmp(argv[i], "mfp"))
        {
          mask |= CUPS_PRINTER_MFP;
          type |= CUPS_PRINTER_MFP;
        }
        else if (!_cups_strcasecmp(argv[i], "printer"))
        {
          mask |= CUPS_PRINTER_MFP;
        }
        else if (!_cups_strcasecmp(argv[i], "large"))
        {
          mask |= CUPS_PRINTER_LARGE;
          type |= CUPS_PRINTER_LARGE;
        }
        else if (!_cups_strcasecmp(argv[i], "medium"))
        {
          mask |= CUPS_PRINTER_MEDIUM;
          type |= CUPS_PRINTER_MEDIUM;
        }
        else if (!_cups_strcasecmp(argv[i], "small"))
        {
          mask |= CUPS_PRINTER_SMALL;
          type |= CUPS_PRINTER_SMALL;
        }
        else
          fprintf(stderr, "Unknown argument \"%s\" ignored...\n", argv[i]);

      cupsEnumDests(CUPS_DEST_FLAGS_NONE, msec, NULL, type, mask, enum_cb, NULL);
    }
    else if (!strcmp(argv[1], "password"))
    {
      const char *pass = cupsGetPassword("Password:"******"Password entered: %s\n", pass);
      else
	puts("No password entered.");
    }
    else if (!strcmp(argv[1], "ppd") && argc == 3)
    {
     /*
      * ./testcups ppd printer
      */

      http_status_t	http_status;	/* Status */
      char		buffer[1024];	/* PPD filename */
      time_t		modtime = 0;	/* Last modified */

      if ((http_status = cupsGetPPD3(CUPS_HTTP_DEFAULT, argv[2], &modtime,
                                     buffer, sizeof(buffer))) != HTTP_STATUS_OK)
        printf("Unable to get PPD: %d (%s)\n", (int)http_status,
               cupsLastErrorString());
      else
        puts(buffer);
    }
    else if (!strcmp(argv[1], "print") && argc == 5)
    {
     /*
      * ./testcups print printer file interval
      */

      int		interval,	/* Interval between writes */
			job_id;		/* Job ID */
      cups_file_t	*fp;		/* Print file */
      char		buffer[16384];	/* Read/write buffer */
      ssize_t		bytes;		/* Bytes read/written */

      if ((fp = cupsFileOpen(argv[3], "r")) == NULL)
      {
	printf("Unable to open \"%s\": %s\n", argv[2], strerror(errno));
	return (1);
      }

      if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, argv[2], "testcups", 0,
				  NULL)) <= 0)
      {
	printf("Unable to create print job on %s: %s\n", argv[1],
	       cupsLastErrorString());
	return (1);
      }

      interval = atoi(argv[4]);

      if (cupsStartDocument(CUPS_HTTP_DEFAULT, argv[1], job_id, argv[2],
			    CUPS_FORMAT_AUTO, 1) != HTTP_STATUS_CONTINUE)
      {
	puts("Unable to start document!");
	return (1);
      }

      while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
      {
	printf("Writing %d bytes...\n", (int)bytes);

	if (cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer,
				 bytes) != HTTP_STATUS_CONTINUE)
	{
	  puts("Unable to write bytes!");
	  return (1);
	}

        if (interval > 0)
	  sleep(interval);
      }

      cupsFileClose(fp);

      if (cupsFinishDocument(CUPS_HTTP_DEFAULT,
                             argv[1]) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED)
      {
	puts("Unable to finish document!");
	return (1);
      }
    }
    else
    {
      puts("Usage:");
      puts("");
      puts("Run basic unit tests:");
      puts("");
      puts("    ./testcups");
      puts("");
      puts("Enumerate printers (for N seconds, -1 for indefinitely):");
      puts("");
      puts("    ./testcups enum [seconds]");
      puts("");
      puts("Ask for a password:"******"");
      puts("    ./testcups password");
      puts("");
      puts("Get the PPD file:");
      puts("");
      puts("    ./testcups ppd printer");
      puts("");
      puts("Print a file (interval controls delay between buffers in seconds):");
      puts("");
      puts("    ./testcups print printer file interval");
      return (1);
    }

    return (0);
  }

 /*
  * cupsGetDests()
  */

  fputs("cupsGetDests: ", stdout);
  fflush(stdout);

  num_dests = cupsGetDests(&dests);

  if (num_dests == 0)
  {
    puts("FAIL");
    return (1);
  }
  else
  {
    printf("PASS (%d dests)\n", num_dests);

    for (i = num_dests, dest = dests; i > 0; i --, dest ++)
    {
      printf("    %s", dest->name);

      if (dest->instance)
        printf("    /%s", dest->instance);

      if (dest->is_default)
        puts(" ***DEFAULT***");
      else
        putchar('\n');
    }
  }

 /*
  * cupsGetDest(NULL)
  */

  fputs("cupsGetDest(NULL): ", stdout);
  fflush(stdout);

  if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
  {
    for (i = num_dests, dest = dests; i > 0; i --, dest ++)
      if (dest->is_default)
        break;

    if (i)
    {
      status = 1;
      puts("FAIL");
    }
    else
      puts("PASS (no default)");

    dest = NULL;
  }
  else
    printf("PASS (%s)\n", dest->name);

 /*
  * cupsGetNamedDest(NULL, NULL, NULL)
  */

  fputs("cupsGetNamedDest(NULL, NULL, NULL): ", stdout);
  fflush(stdout);

  if ((named_dest = cupsGetNamedDest(NULL, NULL, NULL)) == NULL ||
      !dests_equal(dest, named_dest))
  {
    if (!dest)
      puts("PASS (no default)");
    else if (named_dest)
    {
      puts("FAIL (different values)");
      show_diffs(dest, named_dest);
      status = 1;
    }
    else
    {
      puts("FAIL (no default)");
      status = 1;
    }
  }
  else
    printf("PASS (%s)\n", named_dest->name);

  if (named_dest)
    cupsFreeDests(1, named_dest);

 /*
  * cupsGetDest(printer)
  */

  printf("cupsGetDest(\"%s\"): ", dests[num_dests / 2].name);
  fflush(stdout);

  if ((dest = cupsGetDest(dests[num_dests / 2].name, NULL, num_dests,
                          dests)) == NULL)
  {
    puts("FAIL");
    return (1);
  }
  else
    puts("PASS");

 /*
  * cupsGetNamedDest(NULL, printer, instance)
  */

  printf("cupsGetNamedDest(NULL, \"%s\", \"%s\"): ", dest->name,
         dest->instance ? dest->instance : "(null)");
  fflush(stdout);

  if ((named_dest = cupsGetNamedDest(NULL, dest->name,
                                     dest->instance)) == NULL ||
      !dests_equal(dest, named_dest))
  {
    if (named_dest)
    {
      puts("FAIL (different values)");
      show_diffs(dest, named_dest);
    }
    else
      puts("FAIL (no destination)");


    status = 1;
  }
  else
    puts("PASS");

  if (named_dest)
    cupsFreeDests(1, named_dest);

 /*
  * cupsPrintFile()
  */

  fputs("cupsPrintFile: ", stdout);
  fflush(stdout);

  if (cupsPrintFile(dest->name, "../data/testprint", "Test Page",
                    dest->num_options, dest->options) <= 0)
  {
    printf("FAIL (%s)\n", cupsLastErrorString());
    return (1);
  }
  else
    puts("PASS");

 /*
  * cupsGetPPD(printer)
  */

  fputs("cupsGetPPD(): ", stdout);
  fflush(stdout);

  if ((ppdfile = cupsGetPPD(dest->name)) == NULL)
  {
    puts("FAIL");
  }
  else
  {
    puts("PASS");

   /*
    * ppdOpenFile()
    */

    fputs("ppdOpenFile(): ", stdout);
    fflush(stdout);

    if ((ppd = ppdOpenFile(ppdfile)) == NULL)
    {
      puts("FAIL");
      return (1);
    }
    else
      puts("PASS");

    ppdClose(ppd);
    unlink(ppdfile);
  }

 /*
  * cupsGetJobs()
  */

  fputs("cupsGetJobs: ", stdout);
  fflush(stdout);

  num_jobs = cupsGetJobs(&jobs, NULL, 0, -1);

  if (num_jobs == 0)
  {
    puts("FAIL");
    return (1);
  }
  else
    puts("PASS");

  cupsFreeJobs(num_jobs, jobs);
  cupsFreeDests(num_dests, dests);

  return (status);
}
Exemplo n.º 7
0
int					/* O - Number of jobs */
cupsGetJobs2(http_t     *http,		/* I - HTTP connection */
             cups_job_t **jobs,		/* O - Job data */
             const char *mydest,	/* I - NULL = all destinations,       *
	                                 *     otherwise show jobs for mydest */
             int        myjobs,		/* I - 0 = all users, 1 = mine */
             int        completed)	/* I - -1 = show all, 0 = active, *
	                                 *     1 = completed jobs         */
{
    int		n;			/* Number of jobs */
    ipp_t		*request,		/* IPP Request */
                *response;		/* IPP Response */
    ipp_attribute_t *attr;		/* Current attribute */
    cups_job_t	*temp;			/* Temporary pointer */
    int		id,			/* job-id */
            priority,		/* job-priority */
            size;			/* job-k-octets */
    ipp_jstate_t	state;			/* job-state */
    time_t	completed_time,		/* time-at-completed */
            creation_time,		/* time-at-creation */
            processing_time;	/* time-at-processing */
    const char	*dest,			/* job-printer-uri */
           *format,		/* document-format */
           *title,			/* job-name */
           *user;			/* job-originating-user-name */
    char		uri[HTTP_MAX_URI];	/* URI for jobs */
    _cups_globals_t *cg = _cupsGlobals();	/* Pointer to library globals */
    static const char * const attrs[] =	/* Requested attributes */
    {
        "job-id",
        "job-priority",
        "job-k-octets",
        "job-state",
        "time-at-completed",
        "time-at-creation",
        "time-at-processing",
        "job-printer-uri",
        "document-format",
        "job-name",
        "job-originating-user-name"
    };


    /*
     * Range check input...
     */

    if (!http || !jobs)
    {
        _cupsSetError(IPP_INTERNAL_ERROR, NULL);

        return (-1);
    }

    /*
     * Get the right URI...
     */

    if (mydest)
    {
        if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                             "localhost", 0, "/printers/%s", mydest) != HTTP_URI_OK)
        {
            _cupsSetError(IPP_INTERNAL_ERROR, NULL);

            return (-1);
        }
    }
    else
        strcpy(uri, "ipp://localhost/jobs");


    /*
     * Build an IPP_GET_JOBS request, which requires the following
     * attributes:
     *
     *    attributes-charset
     *    attributes-natural-language
     *    printer-uri
     *    requesting-user-name
     *    which-jobs
     *    my-jobs
     *    requested-attributes
     */

    request = ippNewRequest(IPP_GET_JOBS);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
                 "printer-uri", NULL, uri);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                 "requesting-user-name", NULL, cupsUser());

    if (myjobs)
        ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);

    if (completed > 0)
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                     "which-jobs", NULL, "completed");
    else if (completed < 0)
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                     "which-jobs", NULL, "all");

    ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                  "requested-attributes", sizeof(attrs) / sizeof(attrs[0]),
                  NULL, attrs);

    /*
     * Do the request and get back a response...
     */

    n     = 0;
    *jobs = NULL;

    if ((response = cupsDoRequest(http, request, "/")) != NULL)
    {
        for (attr = response->attrs; attr != NULL; attr = attr->next)
        {
            /*
             * Skip leading attributes until we hit a job...
             */

            while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
                attr = attr->next;

            if (attr == NULL)
                break;

            /*
             * Pull the needed attributes from this job...
             */

            id              = 0;
            size            = 0;
            priority        = 50;
            state           = IPP_JOB_PENDING;
            user            = "******";
            dest            = NULL;
            format          = "application/octet-stream";
            title           = "untitled";
            creation_time   = 0;
            completed_time  = 0;
            processing_time = 0;

            while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
            {
                if (strcmp(attr->name, "job-id") == 0 &&
                        attr->value_tag == IPP_TAG_INTEGER)
                    id = attr->values[0].integer;
                else if (strcmp(attr->name, "job-state") == 0 &&
                         attr->value_tag == IPP_TAG_ENUM)
                    state = (ipp_jstate_t)attr->values[0].integer;
                else if (strcmp(attr->name, "job-priority") == 0 &&
                         attr->value_tag == IPP_TAG_INTEGER)
                    priority = attr->values[0].integer;
                else if (strcmp(attr->name, "job-k-octets") == 0 &&
                         attr->value_tag == IPP_TAG_INTEGER)
                    size = attr->values[0].integer;
                else if (strcmp(attr->name, "time-at-completed") == 0 &&
                         attr->value_tag == IPP_TAG_INTEGER)
                    completed_time = attr->values[0].integer;
                else if (strcmp(attr->name, "time-at-creation") == 0 &&
                         attr->value_tag == IPP_TAG_INTEGER)
                    creation_time = attr->values[0].integer;
                else if (strcmp(attr->name, "time-at-processing") == 0 &&
                         attr->value_tag == IPP_TAG_INTEGER)
                    processing_time = attr->values[0].integer;
                else if (strcmp(attr->name, "job-printer-uri") == 0 &&
                         attr->value_tag == IPP_TAG_URI)
                {
                    if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL)
                        dest ++;
                }
                else if (strcmp(attr->name, "job-originating-user-name") == 0 &&
                         attr->value_tag == IPP_TAG_NAME)
                    user = attr->values[0].string.text;
                else if (strcmp(attr->name, "document-format") == 0 &&
                         attr->value_tag == IPP_TAG_MIMETYPE)
                    format = attr->values[0].string.text;
                else if (strcmp(attr->name, "job-name") == 0 &&
                         (attr->value_tag == IPP_TAG_TEXT ||
                          attr->value_tag == IPP_TAG_NAME))
                    title = attr->values[0].string.text;

                attr = attr->next;
            }

            /*
             * See if we have everything needed...
             */

            if (dest == NULL || id == 0)
            {
                if (attr == NULL)
                    break;
                else
                    continue;
            }

            /*
             * Allocate memory for the job...
             */

            if (n == 0)
                temp = malloc(sizeof(cups_job_t));
            else
                temp = realloc(*jobs, sizeof(cups_job_t) * (n + 1));

            if (temp == NULL)
            {
                /*
                 * Ran out of memory!
                 */

                cupsFreeJobs(n, *jobs);
                *jobs = NULL;

                ippDelete(response);
                return (0);
            }

            *jobs = temp;
            temp  += n;
            n ++;

            /*
             * Copy the data over...
             */

            temp->dest            = strdup(dest);
            temp->user            = strdup(user);
            temp->format          = strdup(format);
            temp->title           = strdup(title);
            temp->id              = id;
            temp->priority        = priority;
            temp->state           = state;
            temp->size            = size;
            temp->completed_time  = completed_time;
            temp->creation_time   = creation_time;
            temp->processing_time = processing_time;

            if (attr == NULL)
                break;
        }

        ippDelete(response);
    }

    if (n == 0 && cg->last_error >= IPP_BAD_REQUEST)
        return (-1);
    else
        return (n);
}
static void
update_jobs_list_cb (cups_job_t *jobs,
                     gint        num_of_jobs,
                     gpointer    user_data)
{
  GtkTreeSelection *selection;
  PpJobsDialog     *dialog = (PpJobsDialog *) user_data;
  GtkListStore     *store;
  GtkTreeView      *treeview;
  GtkTreeIter       select_iter;
  GtkTreeIter       iter;
  GSettings        *settings;
  gboolean          select_iter_set = FALSE;
  gint              i;
  gint              select_index = 0;

  treeview = (GtkTreeView*)
    gtk_builder_get_object (dialog->builder, "job-treeview");

  if (dialog->num_jobs > 0)
    cupsFreeJobs (dialog->num_jobs, dialog->jobs);

  dialog->num_jobs = num_of_jobs;
  dialog->jobs = jobs;

  store = gtk_list_store_new (JOB_N_COLUMNS,
                              G_TYPE_INT,
                              G_TYPE_STRING,
                              G_TYPE_STRING,
                              G_TYPE_STRING);

  if (dialog->current_job_id >= 0)
    {
      for (i = 0; i < dialog->num_jobs; i++)
        {
          select_index = i;
          if (dialog->jobs[i].id >= dialog->current_job_id)
            break;
        }
    }

  for (i = 0; i < dialog->num_jobs; i++)
    {
      GDesktopClockFormat  value;
      GDateTime           *time;
      struct tm *ts;
      gchar     *time_string;
      gchar     *state = NULL;

      ts = localtime (&(dialog->jobs[i].creation_time));
      time = g_date_time_new_local (ts->tm_year,
                                    ts->tm_mon,
                                    ts->tm_mday,
                                    ts->tm_hour,
                                    ts->tm_min,
                                    ts->tm_sec);

      settings = g_settings_new (CLOCK_SCHEMA);
      value = g_settings_get_enum (settings, CLOCK_FORMAT_KEY);

      if (value == G_DESKTOP_CLOCK_FORMAT_24H)
        time_string = g_date_time_format (time, "%k:%M");
      else
        time_string = g_date_time_format (time, "%l:%M %p");

      g_date_time_unref (time);

      switch (dialog->jobs[i].state)
        {
          case IPP_JOB_PENDING:
            /* Translators: Job's state (job is waiting to be printed) */
            state = g_strdup (C_("print job", "Pending"));
            break;
          case IPP_JOB_HELD:
            /* Translators: Job's state (job is held for printing) */
            state = g_strdup (C_("print job", "Held"));
            break;
          case IPP_JOB_PROCESSING:
            /* Translators: Job's state (job is currently printing) */
            state = g_strdup (C_("print job", "Processing"));
            break;
          case IPP_JOB_STOPPED:
            /* Translators: Job's state (job has been stopped) */
            state = g_strdup (C_("print job", "Stopped"));
            break;
          case IPP_JOB_CANCELED:
            /* Translators: Job's state (job has been canceled) */
            state = g_strdup (C_("print job", "Canceled"));
            break;
          case IPP_JOB_ABORTED:
            /* Translators: Job's state (job has aborted due to error) */
            state = g_strdup (C_("print job", "Aborted"));
            break;
          case IPP_JOB_COMPLETED:
            /* Translators: Job's state (job has completed successfully) */
            state = g_strdup (C_("print job", "Completed"));
            break;
        }

      gtk_list_store_append (store, &iter);
      gtk_list_store_set (store, &iter,
                          JOB_ID_COLUMN, dialog->jobs[i].id,
                          JOB_TITLE_COLUMN, dialog->jobs[i].title,
                          JOB_STATE_COLUMN, state,
                          JOB_CREATION_TIME_COLUMN, time_string,
                          -1);

      if (i == select_index)
        {
          select_iter = iter;
          select_iter_set = TRUE;
          dialog->current_job_id = dialog->jobs[i].id;
        }

      g_free (time_string);
      g_free (state);
    }

  gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store));

  if (select_iter_set &&
      (selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview))))
    {
      gtk_tree_selection_select_iter (selection, &select_iter);
    }

  g_object_unref (store);
  dialog->ref_count--;
}