コード例 #1
0
ファイル: plugin.c プロジェクト: AlfredArouna/plymouth
static void
show_message (ply_boot_splash_plugin_t *plugin)
{
  ply_list_node_t *node;

  node = ply_list_get_first_node (plugin->views);
  while (node != NULL)
    {
      ply_list_node_t *next_node;
      view_t *view;

      view = ply_list_node_get_data (node);
      next_node = ply_list_get_next_node (plugin->views, node);

      view_show_message (view);

      node = next_node;
    }
}
コード例 #2
0
ファイル: ply-terminal.c プロジェクト: halfline/plymouth
static void
on_tty_input (ply_terminal_t *terminal)
{
    ply_list_node_t *node;

    node = ply_list_get_first_node (terminal->input_closures);
    while (node != NULL) {
        ply_terminal_input_closure_t *closure;
        ply_list_node_t *next_node;

        closure = ply_list_node_get_data (node);
        next_node = ply_list_get_next_node (terminal->input_closures, node);

        if (closure->handler != NULL)
            closure->handler (closure->user_data, terminal);

        node = next_node;
    }
}
コード例 #3
0
ファイル: plugin.c プロジェクト: AlfredArouna/plymouth
static void
unpause_views (ply_boot_splash_plugin_t *plugin)
{
  ply_list_node_t *node;

  node = ply_list_get_first_node (plugin->views);
  while (node != NULL)
    {
      ply_list_node_t *next_node;
      view_t *view;

      view = ply_list_node_get_data (node);
      next_node = ply_list_get_next_node (plugin->views, node);

      ply_text_display_unpause_updates (view->display);

      node = next_node;
    }
}
コード例 #4
0
ファイル: plugin.c プロジェクト: AlfredArouna/plymouth
static void
unpause_displays (ply_boot_splash_plugin_t *plugin)
{
  ply_list_node_t *node;

  node = ply_list_get_first_node (plugin->displays);
  while (node != NULL)
    {
      ply_pixel_display_t *display;
      ply_list_node_t *next_node;

      display = ply_list_node_get_data (node);
      next_node = ply_list_get_next_node (plugin->displays, node);

      ply_pixel_display_unpause_updates (display);

      node = next_node;
    }
}
コード例 #5
0
ファイル: ply-seat.c プロジェクト: magcius/plymouth
static void
free_text_displays (ply_seat_t *seat)
{
        ply_list_node_t *node;

        ply_trace ("freeing %d text displays", ply_list_get_length (seat->text_displays));
        node = ply_list_get_first_node (seat->text_displays);
        while (node != NULL) {
                ply_list_node_t *next_node;
                ply_text_display_t *display;

                next_node = ply_list_get_next_node (seat->text_displays, node);
                display = ply_list_node_get_data (node);
                ply_text_display_free (display);

                ply_list_remove_node (seat->text_displays, node);

                node = next_node;
        }
}
コード例 #6
0
ファイル: plugin.c プロジェクト: magcius/plymouth
static void
show_prompt (ply_boot_splash_plugin_t *plugin,
             const char               *prompt,
             const char               *text)
{
        ply_list_node_t *node;

        node = ply_list_get_first_node (plugin->views);
        while (node != NULL) {
                ply_list_node_t *next_node;
                view_t *view;

                view = ply_list_node_get_data (node);
                next_node = ply_list_get_next_node (plugin->views, node);

                view_show_prompt (view, prompt, text);

                node = next_node;
        }
}
コード例 #7
0
ファイル: plugin.c プロジェクト: AtsKiYsPoYl/plymouth
static void
free_heads (ply_renderer_backend_t *backend)
{
  ply_list_node_t *node;

  node = ply_list_get_first_node (backend->heads);
  while (node != NULL)
    {
      ply_list_node_t *next_node;
      ply_renderer_head_t *head;

      head = (ply_renderer_head_t *) ply_list_node_get_data (node);
      next_node = ply_list_get_next_node (backend->heads, node);

      ply_renderer_head_free (head);
      ply_list_remove_node (backend->heads, node);

      node = next_node;
    }
}
コード例 #8
0
ファイル: plugin.c プロジェクト: AlfredArouna/plymouth
static void
update_progress_animation (ply_boot_splash_plugin_t *plugin,
                           double                    percent_done)
{
  ply_list_node_t *node;

  node = ply_list_get_first_node (plugin->views);
  while (node != NULL)
    {
      ply_list_node_t *next_node;
      view_t *view;

      view = ply_list_node_get_data (node);
      next_node = ply_list_get_next_node (plugin->views, node);

      ply_progress_animation_set_percent_done (view->progress_animation,
                                               percent_done);

      node = next_node;
    }
}
コード例 #9
0
ファイル: ply-region.c プロジェクト: AtsKiYsPoYl/plymouth
void
ply_region_clear (ply_region_t *region)
{
  ply_list_node_t *node;

  node = ply_list_get_first_node (region->rectangle_list);
  while (node != NULL)
    {
      ply_list_node_t *next_node;
      ply_rectangle_t *rectangle;

      rectangle = (ply_rectangle_t *) ply_list_node_get_data (node);

      next_node = ply_list_get_next_node (region->rectangle_list, node);

      free (rectangle);
      ply_list_remove_node (region->rectangle_list, node);

      node = next_node;
    }
}
コード例 #10
0
ファイル: plugin.c プロジェクト: magcius/plymouth
static void
show_password_prompt (ply_boot_splash_plugin_t *plugin,
                      const char               *text,
                      int                       number_of_bullets)
{
        ply_list_node_t *node;

        node = ply_list_get_first_node (plugin->views);
        while (node != NULL) {
                ply_list_node_t *next_node;
                view_t *view;

                view = ply_list_node_get_data (node);
                next_node = ply_list_get_next_node (plugin->views, node);

                view_show_prompt (view, text);
                ply_entry_set_bullet_count (view->entry, number_of_bullets);

                node = next_node;
        }
}
コード例 #11
0
ファイル: plugin.c プロジェクト: halfline/plymouth
static void
system_update (ply_boot_splash_plugin_t *plugin,
               int                       progress)
{
        ply_list_node_t *node;

        if (plugin->mode != PLY_BOOT_SPLASH_MODE_UPDATES)
                return;

        node = ply_list_get_first_node (plugin->views);
        while (node != NULL) {
                ply_list_node_t *next_node;
                view_t *view;

                view = ply_list_node_get_data (node);
                next_node = ply_list_get_next_node (plugin->views, node);
                ply_progress_bar_set_percent_done (view->progress_bar, (double) progress / 100.f);
                ply_progress_bar_draw (view->progress_bar);
                node = next_node;
        }
}
コード例 #12
0
ファイル: plugin.c プロジェクト: halfline/plymouth
static void
show_prompt (ply_boot_splash_plugin_t *plugin,
             const char               *prompt,
             const char               *entry_text)
{
        ply_list_node_t *node;

        ply_trace ("showing prompt");
        node = ply_list_get_first_node (plugin->views);
        while (node != NULL) {
                ply_list_node_t *next_node;
                view_t *view;

                view = ply_list_node_get_data (node);
                next_node = ply_list_get_next_node (plugin->views, node);

                view_show_prompt (view, prompt);
                ply_entry_set_text (view->entry, entry_text);

                node = next_node;
        }
}
コード例 #13
0
ファイル: plugin.c プロジェクト: magcius/plymouth
static void
show_message (ply_boot_splash_plugin_t *plugin,
              const char               *message)
{
        ply_trace ("Showing message '%s'", message);
        ply_list_node_t *node;
        node = ply_list_get_first_node (plugin->views);
        while (node != NULL) {
                ply_list_node_t *next_node;
                view_t *view;

                view = ply_list_node_get_data (node);
                next_node = ply_list_get_next_node (plugin->views, node);
                ply_label_set_text (view->message_label, message);
                ply_label_show (view->message_label, view->display, 10, 10);

                ply_pixel_display_draw_area (view->display, 10, 10,
                                             ply_label_get_width (view->message_label),
                                             ply_label_get_height (view->message_label));
                node = next_node;
        }
}
コード例 #14
0
ファイル: plugin.c プロジェクト: magcius/plymouth
static void
free_stars (view_t *view)
{
        ply_list_node_t *node;

        assert (view != NULL);

        node = ply_list_get_first_node (view->stars);
        while (node != NULL) {
                ply_list_node_t *next_node;
                star_t *star;

                star = (star_t *) ply_list_node_get_data (node);

                next_node = ply_list_get_next_node (view->stars, node);

                star_free (star);
                node = next_node;
        }

        ply_list_free (view->stars);
        view->stars = NULL;
}
コード例 #15
0
ファイル: plugin.c プロジェクト: magcius/plymouth
static void
free_views (ply_boot_splash_plugin_t *plugin)
{
        ply_list_node_t *node;

        node = ply_list_get_first_node (plugin->views);

        while (node != NULL) {
                ply_list_node_t *next_node;
                view_t *view;

                view = ply_list_node_get_data (node);
                next_node = ply_list_get_next_node (plugin->views, node);

                view_free (view);
                ply_list_remove_node (plugin->views, node);

                node = next_node;
        }

        ply_list_free (plugin->views);
        plugin->views = NULL;
}
コード例 #16
0
ファイル: plugin.c プロジェクト: pkt/pkt-plymouth
static bool
encoder_is_available (ply_renderer_backend_t *backend,
                      uint32_t                encoder_id)
{
  ply_list_node_t *node;

  node = ply_list_get_first_node (backend->heads);
  while (node != NULL)
    {
      ply_list_node_t *next_node;
      ply_renderer_head_t *head;

      head = (ply_renderer_head_t *) ply_list_node_get_data (node);
      next_node = ply_list_get_next_node (backend->heads, node);

      if (head->encoder_id == encoder_id)
        return false;

      node = next_node;
    }

  return true;
}
コード例 #17
0
ファイル: plugin.c プロジェクト: AlfredArouna/plymouth
static void
start_animation (ply_boot_splash_plugin_t *plugin)
{
  ply_list_node_t *node;

  assert (plugin != NULL);
  assert (plugin->loop != NULL);

  redraw_views (plugin);

  if (plugin->message != NULL)
    show_message (plugin);

  if (plugin->is_animating)
     return;

  node = ply_list_get_first_node (plugin->views);
  while (node != NULL)
    {
      ply_list_node_t *next_node;
      view_t *view;

      view = ply_list_node_get_data (node);
      next_node = ply_list_get_next_node (plugin->views, node);

      view_start_animation (view);

      node = next_node;
    }

  plugin->is_animating = true;

  animate_frame (plugin, 0);
  ply_event_loop_watch_for_timeout (plugin->loop, 1.0,
                                    (ply_event_loop_timeout_handler_t)
                                    on_timeout, plugin);
}
コード例 #18
0
ファイル: plugin.c プロジェクト: halfline/plymouth
static void
stop_animation (ply_boot_splash_plugin_t *plugin,
                ply_trigger_t            *trigger)
{
        ply_list_node_t *node;

        assert (plugin != NULL);
        assert (plugin->loop != NULL);

        if (!plugin->is_animating)
                return;

        ply_trace ("stopping animation%s",
                   trigger != NULL ? " with trigger" : "");

        plugin->is_animating = false;

        node = ply_list_get_first_node (plugin->views);
        while (node != NULL) {
                ply_list_node_t *next_node;
                view_t *view;

                view = ply_list_node_get_data (node);
                next_node = ply_list_get_next_node (plugin->views, node);

                ply_progress_bar_hide (view->progress_bar);
                if (trigger != NULL)
                        ply_trigger_ignore_next_pull (trigger);
                ply_throbber_stop (view->throbber, trigger);

                node = next_node;
        }

        if (trigger != NULL)
                ply_trigger_pull (trigger, NULL);
}
コード例 #19
0
ファイル: plugin.c プロジェクト: AlfredArouna/plymouth
static void
start_end_animation (ply_boot_splash_plugin_t *plugin,
                     ply_trigger_t            *trigger)
{

  ply_list_node_t *node;

  node = ply_list_get_first_node (plugin->views);
  while (node != NULL)
    {
      ply_list_node_t *next_node;
      view_t *view;

      view = ply_list_node_get_data (node);
      next_node = ply_list_get_next_node (plugin->views, node);

      ply_progress_animation_hide (view->progress_animation);
      ply_trigger_ignore_next_pull (trigger);
      view_start_end_animation (view, trigger);

      node = next_node;
    }
  ply_trigger_pull (trigger, NULL);
}
コード例 #20
0
ファイル: ply-progress.c プロジェクト: AtsKiYsPoYl/plymouth
void
ply_progress_save_cache (ply_progress_t* progress,
                         const char *filename)
{
  FILE *fp;
  ply_list_node_t *node;
  double cur_time = ply_progress_get_time(progress);

  fp = fopen (filename,"w");
  if (fp == NULL)
    return;

  node = ply_list_get_first_node (progress->current_message_list);

  while (node)
    {
      ply_progress_message_t *message = ply_list_node_get_data (node);
      double percentage = message->time / cur_time;
      if (!message->disabled)
          fprintf (fp, "%.3lf:%s\n", percentage, message->string);
      node = ply_list_get_next_node (progress->current_message_list, node);
    }
  fclose (fp);
}
コード例 #21
0
ファイル: plugin.c プロジェクト: magcius/plymouth
static bool
load_views (ply_boot_splash_plugin_t *plugin)
{
        ply_list_node_t *node;
        bool view_loaded;

        view_loaded = false;
        node = ply_list_get_first_node (plugin->views);

        while (node != NULL) {
                ply_list_node_t *next_node;
                view_t *view;

                view = ply_list_node_get_data (node);
                next_node = ply_list_get_next_node (plugin->views, node);

                if (view_load (view))
                        view_loaded = true;

                node = next_node;
        }

        return view_loaded;
}
コード例 #22
0
ファイル: plugin.c プロジェクト: AlfredArouna/plymouth
static void
start_animation (ply_boot_splash_plugin_t *plugin)
{
  ply_list_node_t *node;

  if (plugin->is_animating)
     return;

  node = ply_list_get_first_node (plugin->views);
  while (node != NULL)
    {
      ply_list_node_t *next_node;
      view_t *view;

      view = ply_list_node_get_data (node);
      next_node = ply_list_get_next_node (plugin->views, node);

      view_start_animation (view);

      node = next_node;
    }

  plugin->is_animating = true;
}
コード例 #23
0
ファイル: ply-terminal.c プロジェクト: halfline/plymouth
void
ply_terminal_stop_watching_for_input (ply_terminal_t              *terminal,
                                      ply_terminal_input_handler_t input_handler,
                                      void                        *user_data)
{
    ply_list_node_t *node;

    node = ply_list_get_first_node (terminal->input_closures);
    while (node != NULL) {
        ply_terminal_input_closure_t *closure;
        ply_list_node_t *next_node;

        closure = ply_list_node_get_data (node);
        next_node = ply_list_get_next_node (terminal->input_closures, node);

        if (closure->handler == input_handler &&
                closure->user_data == user_data) {
            free (closure);
            ply_list_remove_node (terminal->input_closures, node);
        }

        node = next_node;
    }
}
コード例 #24
0
ファイル: plugin.c プロジェクト: magcius/plymouth
static void
remove_pixel_display (ply_boot_splash_plugin_t *plugin,
                      ply_pixel_display_t      *display)
{
        ply_list_node_t *node;

        node = ply_list_get_first_node (plugin->views);
        while (node != NULL) {
                view_t *view;
                ply_list_node_t *next_node;

                view = ply_list_node_get_data (node);
                next_node = ply_list_get_next_node (plugin->views, node);

                if (view->display == display) {
                        ply_pixel_display_set_draw_handler (view->display, NULL, NULL);
                        view_free (view);
                        ply_list_remove_node (plugin->views, node);
                        return;
                }

                node = next_node;
        }
}
コード例 #25
0
static void script_parse_exp_free (script_exp_t *exp)
{
  if (!exp) return;
  switch (exp->type)
    {
      case SCRIPT_EXP_TYPE_PLUS:
      case SCRIPT_EXP_TYPE_MINUS:
      case SCRIPT_EXP_TYPE_MUL:
      case SCRIPT_EXP_TYPE_DIV:
      case SCRIPT_EXP_TYPE_MOD:
      case SCRIPT_EXP_TYPE_EQ:
      case SCRIPT_EXP_TYPE_NE:
      case SCRIPT_EXP_TYPE_GT:
      case SCRIPT_EXP_TYPE_GE:
      case SCRIPT_EXP_TYPE_LT:
      case SCRIPT_EXP_TYPE_LE:
      case SCRIPT_EXP_TYPE_AND:
      case SCRIPT_EXP_TYPE_OR:
      case SCRIPT_EXP_TYPE_EXTEND:
      case SCRIPT_EXP_TYPE_ASSIGN:
      case SCRIPT_EXP_TYPE_ASSIGN_PLUS:
      case SCRIPT_EXP_TYPE_ASSIGN_MINUS:
      case SCRIPT_EXP_TYPE_ASSIGN_MUL:
      case SCRIPT_EXP_TYPE_ASSIGN_DIV:
      case SCRIPT_EXP_TYPE_ASSIGN_MOD:
      case SCRIPT_EXP_TYPE_ASSIGN_EXTEND:
      case SCRIPT_EXP_TYPE_HASH:
        script_parse_exp_free (exp->data.dual.sub_a);
        script_parse_exp_free (exp->data.dual.sub_b);
        break;

      case SCRIPT_EXP_TYPE_NOT:
      case SCRIPT_EXP_TYPE_POS:
      case SCRIPT_EXP_TYPE_NEG:
      case SCRIPT_EXP_TYPE_PRE_INC:
      case SCRIPT_EXP_TYPE_PRE_DEC:
      case SCRIPT_EXP_TYPE_POST_INC:
      case SCRIPT_EXP_TYPE_POST_DEC:
        script_parse_exp_free (exp->data.sub);
        break;

      case SCRIPT_EXP_TYPE_TERM_NUMBER:
      case SCRIPT_EXP_TYPE_TERM_NULL:
      case SCRIPT_EXP_TYPE_TERM_LOCAL:
      case SCRIPT_EXP_TYPE_TERM_GLOBAL:
      case SCRIPT_EXP_TYPE_TERM_THIS:
        break;
      case SCRIPT_EXP_TYPE_TERM_SET:
        {
          ply_list_node_t *node;
          for (node = ply_list_get_first_node (exp->data.parameters);
               node;
               node = ply_list_get_next_node (exp->data.parameters, node))
            {
              script_exp_t *sub = ply_list_node_get_data (node);
              script_parse_exp_free (sub);
            }
          ply_list_free (exp->data.parameters);
          break;
        }
      case SCRIPT_EXP_TYPE_FUNCTION_EXE:
        {
          ply_list_node_t *node;
          for (node = ply_list_get_first_node (exp->data.function_exe.parameters);
               node;
               node = ply_list_get_next_node (exp->data.function_exe.parameters, node))
            {
              script_exp_t *sub = ply_list_node_get_data (node);
              script_parse_exp_free (sub);
            }
          ply_list_free (exp->data.function_exe.parameters);
          script_parse_exp_free (exp->data.function_exe.name);
          break;
        }
      case SCRIPT_EXP_TYPE_FUNCTION_DEF:   /* FIXME merge the frees with one from op_free */
        {
          if (exp->data.function_def->type == SCRIPT_FUNCTION_TYPE_SCRIPT) 
            script_parse_op_free (exp->data.function_def->data.script);
          ply_list_node_t *node;
          for (node = ply_list_get_first_node (exp->data.function_def->parameters);
               node;
               node = ply_list_get_next_node (exp->data.function_def->parameters, node))
            {
              char *arg = ply_list_node_get_data (node);
              free (arg);
            }
          ply_list_free (exp->data.function_def->parameters);
          free (exp->data.function_def);
          break;
        }

      case SCRIPT_EXP_TYPE_TERM_STRING:
      case SCRIPT_EXP_TYPE_TERM_VAR:
        free (exp->data.string);
        break;
    }
  script_debug_remove_element (exp);
  free (exp);
}
コード例 #26
0
ファイル: ply-boot-server.c プロジェクト: pkt/pkt-plymouth
static void
ply_boot_connection_on_request (ply_boot_connection_t *connection)
{
  ply_boot_server_t *server;
  char *command, *argument;

  assert (connection != NULL);
  assert (connection->fd >= 0);

  server = connection->server;
  assert (server != NULL);

  if (!ply_boot_connection_read_request (connection,
                                         &command, &argument))
    {
      ply_trace ("could not read connection request");
      return;
    }

  if (!ply_boot_connection_is_from_root (connection))
    {
      ply_error ("request came from non-root user");

      if (!ply_write (connection->fd,
                      PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK,
                      strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK)))
        ply_error ("could not write bytes: %m");

      free (command);
      return;
    }

  if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_UPDATE) == 0)
    {
      ply_trace ("got update request");
      if (server->update_handler != NULL)
        server->update_handler (server->user_data, argument, server);
      free (argument);
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_SYSTEM_INITIALIZED) == 0)
    {
      ply_trace ("got system initialized notification");
      if (server->system_initialized_handler != NULL)
        server->system_initialized_handler (server->user_data, server);
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_ERROR) == 0)
    {
      ply_trace ("got error notification");
      if (server->error_handler != NULL)
        server->error_handler (server->user_data, server);
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_SHOW_SPLASH) == 0)
    {
      ply_trace ("got show splash request");
      if (server->show_splash_handler != NULL)
        server->show_splash_handler (server->user_data, server);
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_HIDE_SPLASH) == 0)
    {
      ply_trace ("got hide splash request");
      if (server->hide_splash_handler != NULL)
        server->hide_splash_handler (server->user_data, server);
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_DEACTIVATE) == 0)
    {
      ply_trigger_t *deactivate_trigger;

      ply_trace ("got deactivate request");

      deactivate_trigger = ply_trigger_new (NULL);

      ply_trigger_add_handler (deactivate_trigger,
                               (ply_trigger_handler_t)
                               ply_boot_connection_on_deactivated,
                               connection);

      if (server->deactivate_handler != NULL)
        server->deactivate_handler (server->user_data, deactivate_trigger, server);

      free (argument);
      free (command);
      return;
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_REACTIVATE) == 0)
    {
      ply_trace ("got reactivate request");
      if (server->reactivate_handler != NULL)
        server->reactivate_handler (server->user_data, server);
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUIT) == 0)
    {
      bool retain_splash;
      ply_trigger_t *quit_trigger;

      retain_splash = (bool) argument[0];

      ply_trace ("got quit %srequest", retain_splash? "--retain-splash " : "");

      quit_trigger = ply_trigger_new (NULL);

      ply_trigger_add_handler (quit_trigger,
                               (ply_trigger_handler_t)
                               ply_boot_connection_on_quit_complete,
                               connection);

      if (server->quit_handler != NULL)
        server->quit_handler (server->user_data, retain_splash, quit_trigger, server);

      free(argument);
      free(command);
      return;
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PASSWORD) == 0)
    {
      ply_trigger_t *answer;

      ply_trace ("got password request");

      answer = ply_trigger_new (NULL);
      ply_trigger_add_handler (answer,
                               (ply_trigger_handler_t)
                               ply_boot_connection_on_password_answer,
                               connection);

      if (server->ask_for_password_handler != NULL)
        server->ask_for_password_handler (server->user_data,
                                          argument,
                                          answer,
                                          server);
      /* will reply later
       */
      free(command);
      return;
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_CACHED_PASSWORD) == 0)
    {
      ply_list_node_t *node;
      ply_buffer_t *buffer;
      size_t buffer_size;
      uint32_t size;

      ply_trace ("got cached password request");

      buffer = ply_buffer_new ();

      node = ply_list_get_first_node (server->cached_passwords);

      ply_trace ("There are %d cached passwords",
                 ply_list_get_length (server->cached_passwords));

      /* Add each answer separated by their NUL terminators into
       * a buffer that we write out to the client
       */
      while (node != NULL)
        {
          ply_list_node_t *next_node;
          const char *password;

          next_node = ply_list_get_next_node (server->cached_passwords, node);
          password = (const char *) ply_list_node_get_data (node);

          ply_buffer_append_bytes (buffer,
                                   password,
                                   strlen (password) + 1);
          node = next_node;
        }

      buffer_size = ply_buffer_get_size (buffer);

      /* splash plugin doesn't have any cached passwords
      */
      if (buffer_size == 0)
        {
          if (!ply_write (connection->fd,
                          PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NO_ANSWER,
                          strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NO_ANSWER)))
              ply_error ("could not write bytes: %m");
        }
      else
        {
          size = buffer_size;

          ply_trace ("writing %d cached answers",
                     ply_list_get_length (server->cached_passwords));
          if (!ply_write (connection->fd,
                          PLY_BOOT_PROTOCOL_RESPONSE_TYPE_MULTIPLE_ANSWERS,
                          strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_MULTIPLE_ANSWERS)) ||
              !ply_write_uint32 (connection->fd,
                                 size) ||
              !ply_write (connection->fd,
                          ply_buffer_get_bytes (buffer), size))
              ply_error ("could not write bytes: %m");
        }

      ply_buffer_free (buffer);
      free(command);
      return;
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUESTION) == 0)
    {
      ply_trigger_t *answer;

      ply_trace ("got question request");

      answer = ply_trigger_new (NULL);
      ply_trigger_add_handler (answer,
                               (ply_trigger_handler_t)
                               ply_boot_connection_on_question_answer,
                               connection);

      if (server->ask_question_handler != NULL)
        server->ask_question_handler (server->user_data,
                                          argument,
                                          answer,
                                          server);
      /* will reply later
       */
      free(command);
      return;
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_MESSAGE) == 0)
    {
      ply_trace ("got message request");
      if (server->display_message_handler != NULL)
        server->display_message_handler(server->user_data, argument, server);
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE) == 0)
    {
      ply_trigger_t *answer;

      ply_trace ("got keystroke request");

      answer = ply_trigger_new (NULL);
      ply_trigger_add_handler (answer,
                               (ply_trigger_handler_t)
                               ply_boot_connection_on_keystroke_answer,
                               connection);

      if (server->watch_for_keystroke_handler != NULL)
        server->watch_for_keystroke_handler (server->user_data,
                                          argument,
                                          answer,
                                          server);
      /* will reply later
       */
      free(command);
      return;
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE_REMOVE) == 0)
    {
      ply_trace ("got keystroke remove request");
      if (server->ignore_keystroke_handler != NULL)
        server->ignore_keystroke_handler (server->user_data,
                                          argument,
                                          server);
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PROGRESS_PAUSE) == 0)
    {
      ply_trace ("got progress pause request");
      if (server->progress_pause_handler != NULL)
        server->progress_pause_handler (server->user_data,
                                        server);
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PROGRESS_UNPAUSE) == 0)
    {
      ply_trace ("got progress unpause request");
      if (server->progress_unpause_handler != NULL)
        server->progress_unpause_handler (server->user_data,
                                          server);
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_NEWROOT) == 0)
    {
      ply_trace ("got newroot request");
      if (server->newroot_handler != NULL)
        server->newroot_handler(server->user_data, argument, server);
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_HAS_ACTIVE_VT) == 0)
    {
      bool answer = false;

      ply_trace ("got has_active vt? request");
      if (server->has_active_vt_handler != NULL)
        answer = server->has_active_vt_handler(server->user_data, server);

      if (!answer)
        {
          if (!ply_write (connection->fd,
                          PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK,
                          strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK)))
            ply_error ("could not write bytes: %m");

          free(command);
          return;
        }
    }
  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PING) != 0)
    {
      ply_error ("received unknown command '%s' from client", command);

      if (!ply_write (connection->fd,
                      PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK,
                      strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK)))
        ply_error ("could not write bytes: %m");

      free(command);
      return;
    }

  if (!ply_write (connection->fd, 
                  PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK,
                  strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK)))
    {
      ply_error ("could not write bytes: %m");
    }
  free(command);
}
コード例 #27
0
ファイル: plugin.c プロジェクト: AtsKiYsPoYl/plymouth
static bool
create_heads_for_active_connectors (ply_renderer_backend_t *backend)
{
  int i;
  drmModeConnector *connector;
  ply_hashtable_t *heads_by_controller_id;

  heads_by_controller_id = ply_hashtable_new (NULL, NULL);

  for (i = 0; i < backend->resources->count_connectors; i++)
    {
      ply_renderer_head_t *head;
      drmModeEncoder *encoder;
      uint32_t encoder_id;
      drmModeCrtc *controller;
      uint32_t controller_id;
      uint32_t console_buffer_id;
      int connector_mode_index;

      connector = drmModeGetConnector (backend->device_fd,
                                       backend->resources->connectors[i]);

      if (connector == NULL)
        continue;

      if (connector->connection != DRM_MODE_CONNECTED)
        {
          drmModeFreeConnector (connector);
          continue;
        }

      if (connector->count_modes <= 0)
        {
          drmModeFreeConnector (connector);
          continue;
        }

      encoder = find_encoder_for_connector (backend, connector);

      if (encoder == NULL)
        {
          drmModeFreeConnector (connector);
          continue;
        }

      encoder_id = encoder->encoder_id;
      controller = find_controller_for_encoder (backend, encoder);
      drmModeFreeEncoder (encoder);

      if (controller == NULL)
        {
          drmModeFreeConnector (connector);
          continue;
        }

      controller_id = controller->crtc_id;

      connector_mode_index = get_index_of_active_mode (backend, controller, connector);

      /* If we couldn't find the current active mode, fall back to the first available.
       */
      if (connector_mode_index < 0)
        {
          ply_trace ("falling back to first available mode");
          connector_mode_index = 0;
        }

      console_buffer_id = controller->buffer_id;
      drmModeFreeCrtc (controller);

      head = ply_hashtable_lookup (heads_by_controller_id,
                                   (void *) (intptr_t) controller_id);

      if (head == NULL)
        {
          head = ply_renderer_head_new (backend, connector, connector_mode_index,
                                        encoder_id, controller_id,
                                        console_buffer_id);

          ply_list_append_data (backend->heads, head);

          ply_hashtable_insert (heads_by_controller_id,
                                (void *) (intptr_t) controller_id,
                                head);
        }
      else
        {
          if (!ply_renderer_head_add_connector (head, connector, connector_mode_index))
            {
              ply_trace ("couldn't connect monitor to existing head");
            }

          drmModeFreeConnector (connector);
        }
    }

  ply_hashtable_free (heads_by_controller_id);

#ifdef PLY_ENABLE_DEPRECATED_GDM_TRANSITION
  /* If the driver doesn't support mapping the fb console
   * then we can't get a smooth crossfade transition to
   * the display manager unless we use the /dev/fb interface
   * or the plymouth deactivate interface.
   *
   * In multihead configurations, we'd rather have working
   * multihead, but otherwise bail now.
   */
  if (!backend->driver_supports_mapping_console &&
      ply_list_get_length (backend->heads) == 1)
    {
      ply_list_node_t *node;
      ply_renderer_head_t *head;

      node = ply_list_get_first_node (backend->heads);
      head = (ply_renderer_head_t *) ply_list_node_get_data (node);

      if (ply_array_get_size (head->connector_ids) == 1)
        {
          ply_trace ("Only one monitor configured, and driver doesn't "
                     "support mapping console, so letting frame-buffer "
                     "take over");

          free_heads (backend);
          return false;
        }
    }
#endif

  return ply_list_get_length (backend->heads) > 0;
}
コード例 #28
0
ファイル: ply-boot-client.c プロジェクト: pkt/pkt-plymouth
static void
ply_boot_client_process_incoming_replies (ply_boot_client_t *client)
{
  ply_list_node_t *request_node;
  ply_boot_client_request_t *request;
  bool processed_reply;
  uint8_t byte[2] = "";
  uint32_t size;

  assert (client != NULL);

  processed_reply = false;
  if (ply_list_get_length (client->requests_waiting_for_replies) == 0)
    {
      ply_error ("received unexpected response from boot status daemon");
      return;
    }

  if (!ply_read (client->socket_fd, byte, sizeof (uint8_t)))
    goto out;

  for (request_node = ply_list_get_first_node (client->requests_waiting_for_replies);
       request_node; request_node = ply_list_get_next_node (client->requests_waiting_for_replies, request_node))
    {
      assert (request_node != NULL);
      request = (ply_boot_client_request_t *) ply_list_node_get_data (request_node);
      assert (request != NULL);

      if (! strcmp (request->command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PASSWORD)
          || ! strcmp (request->command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUESTION)
          || ! strcmp (request->command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE))
        {
          if (! memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ANSWER, sizeof (uint8_t))
              || ! memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NO_ANSWER, sizeof (uint8_t)))
            break;
        }
      else
        {
          if (memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ANSWER, sizeof (uint8_t))
              && memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NO_ANSWER, sizeof (uint8_t)))
            break;
        }
    }

  if (memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK, sizeof (uint8_t)) == 0)
      request->handler (request->user_data, client);
  else if (memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ANSWER, sizeof (uint8_t)) == 0)
    {
      char *answer;

      if (!ply_read_uint32 (client->socket_fd, &size))
        goto out;
      
      answer = malloc ((size+1) * sizeof(char));
      if (size > 0)
        {
          if (!ply_read (client->socket_fd, answer, size))
            goto out;
        }

      answer[size] = '\0';
      ((ply_boot_client_answer_handler_t) request->handler) (request->user_data, answer, client);
      free(answer);
    }
  else if (memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_MULTIPLE_ANSWERS, sizeof (uint8_t)) == 0)
    {
      ply_array_t *array;
      char **answers;
      char *answer;
      char *p;
      char *q;
      uint8_t i;

      array = NULL;
      answers = NULL;

      if (!ply_read_uint32 (client->socket_fd, &size))
        goto out;

      assert (size > 0);

      answer = malloc (size);

      if (!ply_read (client->socket_fd, answer, size))
        {
          free (answer);
          goto out;
        }

      array = ply_array_new ();

      p = answer;
      q = p;
      for (i = 0; i < size; i++, q++)
        {
          if (*q == '\0')
            {
              ply_array_add_element (array, strdup (p));
              p = q + 1;
            }
        }
      free (answer);

      answers = (char **) ply_array_steal_elements (array);
      ply_array_free (array);

      ((ply_boot_client_multiple_answers_handler_t) request->handler) (request->user_data, (const char * const *) answers, client);

      ply_free_string_array (answers);
    }
  else if (memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NO_ANSWER, sizeof (uint8_t)) == 0)
    {
      ((ply_boot_client_answer_handler_t) request->handler) (request->user_data, NULL, client);
    }
  else
    goto out;

  processed_reply = true;

out:
  if (!processed_reply)
    {
      if (request->failed_handler != NULL)
        request->failed_handler (request->user_data, client);
    }

  ply_list_remove_node (client->requests_waiting_for_replies, request_node);

  if (ply_list_get_length (client->requests_waiting_for_replies) == 0)
    {
      if (client->daemon_has_reply_watch != NULL)
        {
          assert (client->loop != NULL);
          ply_event_loop_stop_watching_fd (client->loop,
                                           client->daemon_has_reply_watch);
          client->daemon_has_reply_watch = NULL;
        }
    }
}
コード例 #29
0
ファイル: plugin.c プロジェクト: magcius/plymouth
static void
view_add_star (view_t *view)
{
        ply_boot_splash_plugin_t *plugin;
        ply_rectangle_t logo_area;
        star_t *star;
        unsigned int x, y;
        unsigned int width, height;
        unsigned long screen_width, screen_height;
        ply_list_node_t *node;

        assert (view != NULL);

        plugin = view->plugin;

        screen_width = ply_pixel_display_get_width (view->display);
        screen_height = ply_pixel_display_get_height (view->display);
        width = ply_image_get_width (plugin->logo_image);
        height = ply_image_get_height (plugin->logo_image);
        logo_area.x = (screen_width / 2) - (width / 2);
        logo_area.y = (screen_height / 2) - (height / 2);
        logo_area.width = width;
        logo_area.height = height;

        width = ply_image_get_width (plugin->star_image);
        height = ply_image_get_height (plugin->star_image);

        node = NULL;
        do {
                x = rand () % screen_width;
                y = rand () % screen_height;

                if ((x <= logo_area.x + logo_area.width)
                    && (x >= logo_area.x)
                    && (y >= logo_area.y)
                    && (y <= logo_area.y + logo_area.height))
                        continue;

                if ((x + width >= logo_area.x)
                    && (x + width <= logo_area.x + logo_area.width)
                    && (y + height >= logo_area.y)
                    && (y + height <= logo_area.y + logo_area.height))
                        continue;

                node = ply_list_get_first_node (view->stars);
                while (node != NULL) {
                        ply_list_node_t *next_node;

                        star = (star_t *) ply_list_node_get_data (node);
                        next_node = ply_list_get_next_node (view->stars, node);

                        if ((x <= star->x + width)
                            && (x >= star->x)
                            && (y >= star->y)
                            && (y <= star->y + height))
                                break;

                        if ((x + width >= star->x)
                            && (x + width <= star->x + width)
                            && (y + height >= star->y)
                            && (y + height <= star->y + height))
                                break;

                        node = next_node;
                }
        } while (node != NULL);

        star = star_new (x, y, (double) ((rand () % 50) + 1));
        ply_list_append_data (view->stars, star);
}
コード例 #30
0
ファイル: ply-region.c プロジェクト: AtsKiYsPoYl/plymouth
static void
merge_rectangle_with_sub_list (ply_region_t    *region,
                               ply_rectangle_t *new_area,
                               ply_list_node_t *node)
{

  if (ply_rectangle_is_empty (new_area))
    {
      free (new_area);
      return;
    }

  while (node != NULL)
    {
      ply_list_node_t *next_node;
      ply_rectangle_t *old_area;
      ply_rectangle_overlap_t overlap;

      old_area = (ply_rectangle_t *) ply_list_node_get_data (node);

      next_node = ply_list_get_next_node (region->rectangle_list, node);

      if (ply_rectangle_is_empty (new_area))
        overlap = PLY_RECTANGLE_OVERLAP_NO_EDGES;
      else if (ply_rectangle_is_empty (old_area))
        overlap = PLY_RECTANGLE_OVERLAP_ALL_EDGES;
      else
        overlap = ply_rectangle_find_overlap (old_area, new_area);

      switch (overlap)
        {
          /* NNNN      The new rectangle and node rectangle don't touch,
           * NNNN OOOO so let's move on to the next one.
           *      OOOO
           */
          case PLY_RECTANGLE_OVERLAP_NONE:
          break;

          /* NNNNN   We need to split the new rectangle into
           * NNOOOOO two rectangles:  The top row of Ns and
           * NNOOOOO the left side of Ns.
           *   OOOOO
           */
          case PLY_RECTANGLE_OVERLAP_TOP_AND_LEFT_EDGES:
            {
              ply_rectangle_t *rectangle;

              rectangle = copy_rectangle (new_area);
              rectangle->y = old_area->y;
              rectangle->width = old_area->x - new_area->x;
              rectangle->height = (new_area->y + new_area->height) - old_area->y;

              merge_rectangle_with_sub_list (region, rectangle, next_node);

              new_area->height = old_area->y - new_area->y;
            }
          break;

          /*   NNNNN We need to split the new rectangle into
           * OOOOONN two rectangles:  The top row of Ns and
           * OOOOONN the right side of Ns.
           * OOOOO
           */
          case PLY_RECTANGLE_OVERLAP_TOP_AND_RIGHT_EDGES:
            {
              ply_rectangle_t *rectangle;

              rectangle = copy_rectangle (new_area);
              rectangle->x = old_area->x + old_area->width;
              rectangle->y = old_area->y;
              rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width);
              rectangle->height = (new_area->y + new_area->height) - old_area->y;

              merge_rectangle_with_sub_list (region, rectangle, next_node);

              new_area->height = old_area->y - new_area->y;
            }
          break;

          /* NNNNNNN We need to trim out the part of
           * NOOOOON old rectangle that overlaps the new
           * NOOOOON rectangle by shrinking and moving it
           *  OOOOO  and then we need to add the new rectangle.
           */
          case PLY_RECTANGLE_OVERLAP_TOP_AND_SIDE_EDGES:
            {
              old_area->height = (old_area->y + old_area->height)
                                 - (new_area->y + new_area->height);
              old_area->y = new_area->y + new_area->height;
            }
          break;

          /*   NNN  We only care about the top row of Ns,
           *  ONNNO everything below that is already handled by
           *  ONNNO the old rectangle.
           *  OOOOO
           */
          case PLY_RECTANGLE_OVERLAP_TOP_EDGE:
            new_area->height = old_area->y - new_area->y;
          break;

          /*   OOOOO We need to split the new rectangle into
           * NNOOOOO two rectangles:  The left side of Ns and
           * NNOOOOO the bottom row of Ns.
           * NNOOOOO
           * NNNNN
           */
          case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_LEFT_EDGES:
            {
              ply_rectangle_t *rectangle;

              rectangle = copy_rectangle (new_area);

              rectangle->width = old_area->x - new_area->x;
              rectangle->height = (old_area->y + old_area->height) - new_area->y;

              merge_rectangle_with_sub_list (region, rectangle, next_node);

              new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
              new_area->y = old_area->y + old_area->height;
            }
          break;

          /*   OOOOO   We need to split the new rectangle into
           *   OOOOONN two rectangles:  The right side of Ns and
           *   OOOOONN the bottom row of Ns.
           *   OOOOONN
           *     NNNNN
           */
          case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_RIGHT_EDGES:
            {
              ply_rectangle_t *rectangle;

              rectangle = copy_rectangle (new_area);

              rectangle->x = old_area->x + old_area->width;
              rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width);
              rectangle->height = (old_area->y + old_area->height) - new_area->y;

              merge_rectangle_with_sub_list (region, rectangle, next_node);

              new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
              new_area->y = old_area->y + old_area->height;
            }
          break;

          /*  OOOOO  We need to trim out the part of
           * NOOOOON old rectangle that overlaps the new
           * NOOOOON rectangle by shrinking it
           * NNNNNNN and then we need to add the new rectangle.
           */
          case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_SIDE_EDGES:
            {
              old_area->height = new_area->y - old_area->y;
            }
          break;

          /*  OOOOO We only care about the bottom row of Ns,
           *  ONNNO everything above that is already handled by
           *  ONNNO the old rectangle.
           *   NNN
           */
          case PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE:
            {
              new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
              new_area->y = old_area->y + old_area->height;
            }
          break;

          /*  NNNN   We need to trim out the part of
           *  NNNNO  old rectangle that overlaps the new
           *  NNNNO  rectangle by shrinking it and moving it
           *  NNNN   and then we need to add the new rectangle.
           */
          case PLY_RECTANGLE_OVERLAP_TOP_LEFT_AND_BOTTOM_EDGES:
            {
              old_area->width = (old_area->x + old_area->width)
                                 - (new_area->x + new_area->width);
              old_area->x = new_area->x + new_area->width;
            }
          break;

          /*  NNNN  We need to trim out the part of
           * ONNNN  old rectangle that overlaps the new
           * ONNNN  rectangle by shrinking it and then we
           *  NNNN  need to add the new rectangle.
           */
          case PLY_RECTANGLE_OVERLAP_TOP_RIGHT_AND_BOTTOM_EDGES:
            old_area->width = new_area->x - old_area->x;
          break;

          /* NNNNNNN The old rectangle is completely inside the new rectangle
           * NOOOOON so replace the old rectangle with the new rectangle.
           * NOOOOON
           * NNNNNNN
           */
          case PLY_RECTANGLE_OVERLAP_ALL_EDGES:
            merge_rectangle_with_sub_list (region, new_area, next_node);
            free (old_area);
            ply_list_remove_node (region->rectangle_list, node);
          return;

          /*  NNN  We need to split the new rectangle into
           * ONNNO two rectangles: the top and bottom row of Ns
           * ONNNO
           *  NNN
           */
          case PLY_RECTANGLE_OVERLAP_TOP_AND_BOTTOM_EDGES:
            {
              ply_rectangle_t *rectangle;

              rectangle = copy_rectangle (new_area);
              rectangle->y = old_area->y + old_area->height;
              rectangle->width = new_area->width;
              rectangle->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
              merge_rectangle_with_sub_list (region, rectangle, next_node);

              new_area->height = old_area->y - new_area->y;
            }
          break;

          /*  OOOOO We only care about the side row of Ns,
           * NNNNOO everything rigth of that is already handled by
           * NNNNOO the old rectangle.
           *  OOOOO
           */
          case PLY_RECTANGLE_OVERLAP_LEFT_EDGE:
            new_area->width = old_area->x - new_area->x;
          break;

          /* OOOOO  We only care about the side row of Ns,
           * NNNNNN everything left of that is already handled by
           * NNNNNN the old rectangle.
           * OOOOO
           */
          case PLY_RECTANGLE_OVERLAP_RIGHT_EDGE:
            {
              long temp = new_area->x;
              new_area->x = old_area->x + old_area->width;
              new_area->width = (temp + new_area->width) - (old_area->x + old_area->width);
            }
          break;

          /*  OOOOO  We need to split the new rectangle into
           * NNNNNNN two rectangles: the side columns of Ns
           * NNNNNNN
           *  OOOOO
           */
          case PLY_RECTANGLE_OVERLAP_SIDE_EDGES:
            {
              ply_rectangle_t *rectangle;

              rectangle = copy_rectangle (new_area);

              rectangle->x = old_area->x + old_area->width;
              rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width);

              merge_rectangle_with_sub_list (region, rectangle, next_node);

              new_area->width = old_area->x - new_area->x;
            }
          break;

          /* OOOOOOO The new rectangle is completely inside an old rectangle
           * ONNNNNO so return early without adding the new rectangle.
           * ONNNNNO
           * OOOOOOO
           */
          case PLY_RECTANGLE_OVERLAP_NO_EDGES:
            free (new_area);
          return;

          /*  NNNNN We expand the old rectangle up and throw away the new.
           *  NNNNN We must merge it because the new region may have overlapped
           *  NNNNN something further down the list.
           *  OOOOO
           */
          case PLY_RECTANGLE_OVERLAP_EXACT_TOP_EDGE:
            {
              old_area->height = (old_area->y + old_area->height) - new_area->y;
              old_area->y = new_area->y;
              free (new_area);
              merge_rectangle_with_sub_list (region, old_area, next_node);
              ply_list_remove_node (region->rectangle_list, node);
            }
          return;

          /*  OOOOO We expand the old rectangle down and throw away the new.
           *  NNNNN We must merge it because the new region may have overlapped
           *  NNNNN something further down the list.
           *  NNNNN
           */
          case PLY_RECTANGLE_OVERLAP_EXACT_BOTTOM_EDGE:
            {
              old_area->height = (new_area->y + new_area->height) - old_area->y;
              free (new_area);
              merge_rectangle_with_sub_list (region, old_area, next_node);
              ply_list_remove_node (region->rectangle_list, node);
            }
          return;

          /*  NNNNNO We expand the old rectangle left and throw away the new.
           *  NNNNNO We must merge it because the new region may have overlapped
           *  NNNNNO something further down the list.
           */
          case PLY_RECTANGLE_OVERLAP_EXACT_LEFT_EDGE:
            {
              old_area->width = (old_area->x + old_area->width) - new_area->x;
              old_area->x = new_area->x;
              free (new_area);
              merge_rectangle_with_sub_list (region, old_area, next_node);
              ply_list_remove_node (region->rectangle_list, node);
            }
          return;

          /*  ONNNNN We expand the old rectangle right and throw away the new.
           *  ONNNNN We must merge it because the new region may have overlapped
           *  ONNNNN something further down the list.
           */
          case PLY_RECTANGLE_OVERLAP_EXACT_RIGHT_EDGE:
            {
              old_area->width = (new_area->x + new_area->width) - old_area->x;
              free (new_area);
              merge_rectangle_with_sub_list (region, old_area, next_node);
              ply_list_remove_node (region->rectangle_list, node);
            }
          return;


        }

      node = ply_list_get_next_node (region->rectangle_list, node);
    }

  ply_list_append_data (region->rectangle_list, new_area);
}