Esempio n. 1
0
/* Function nano_realloc
 * Implement realloc by malloc + memcpy */
void * nano_realloc(RARG void * ptr, malloc_size_t size)
{
    void * mem;
    chunk * p_to_realloc;

    if (ptr == NULL) return nano_malloc(RCALL size);

    if (size == 0)
    {
        nano_free(RCALL ptr);
        return NULL;
    }

    /* TODO: There is chance to shrink the chunk if newly requested
     * size is much small */
    if (nano_malloc_usable_size(RCALL ptr) >= size)
      return ptr;

    mem = nano_malloc(RCALL size);
    if (mem != NULL)
    {
        memcpy(mem, ptr, size);
        nano_free(RCALL ptr);
    }
    return mem;
}
Esempio n. 2
0
/*
 * Initialize a graphics window.
 */
void nanoglk_wingraphics_init(winid_t win)
{
   win->data = nano_malloc(sizeof(struct graphics));
   struct graphics *g = (struct graphics*)win->data;
   g->bg = nanoglk_buffer_font[style_Normal]->bg; // To have one background.
   nanoglk_wingraphics_clear(win);
}
Esempio n. 3
0
/*
 * Create a file reference with a given name, given flags, and a given
 * rock. Called by all other functions, which return a new file
 * reference.
 */
frefid_t create_by_name(glui32 usage, char *name, glui32 rock)
{
   frefid_t fref = (frefid_t)nano_malloc(sizeof(struct glk_fileref_struct));
   fref->usage = usage;
   fref->rock = rock;
   fref->name = strdup(name);
   ADD(fref);
   return fref;
}
Esempio n. 4
0
/* Function nano_memalign
 * Allocate memory block aligned at specific boundary.
 *   align: required alignment. Must be power of 2. Return NULL
 *          if not power of 2. Undefined behavior is bigger than
 *          pointer value range.
 *   s: required size.
 * Return: allocated memory pointer aligned to align
 * Algorithm: Malloc a big enough block, padding pointer to aligned
 *            address, then truncate and free the tail if too big.
 *            Record the offset of align pointer and original pointer
 *            in the padding area.
 */
void * nano_memalign(RARG size_t align, size_t s)
{
    chunk * chunk_p;
    malloc_size_t size_allocated, offset, ma_size, size_with_padding;
    char * allocated, * aligned_p;

    /* Return NULL if align isn't power of 2 */
    if ((align & (align-1)) != 0) return NULL;

    align = MAX(align, MALLOC_ALIGN);
    ma_size = ALIGN_TO(MAX(s, MALLOC_MINSIZE), CHUNK_ALIGN);
    size_with_padding = ma_size + align - MALLOC_ALIGN;

    allocated = nano_malloc(RCALL size_with_padding);
    if (allocated == NULL) return NULL;

    chunk_p = get_chunk_from_ptr(allocated);
    aligned_p = (char *)ALIGN_TO(
                  (unsigned long)((char *)chunk_p + CHUNK_OFFSET),
                  (unsigned long)align);
    offset = aligned_p - ((char *)chunk_p + CHUNK_OFFSET);

    if (offset)
    {
        if (offset >= MALLOC_MINCHUNK)
        {
            /* Padding is too large, free it */
            chunk * front_chunk = chunk_p;
            chunk_p = (chunk *)((char *)chunk_p + offset);
            chunk_p->size = front_chunk->size - offset;
            front_chunk->size = offset;
            nano_free(RCALL (char *)front_chunk + CHUNK_OFFSET);
        }
        else
        {
            /* Padding is used. Need to set a jump offset for aligned pointer
            * to get back to chunk head */
            assert(offset >= sizeof(int));
            *(int *)((char *)chunk_p + offset) = -offset;
        }
    }

    size_allocated = chunk_p->size;
    if ((char *)chunk_p + size_allocated >
         (aligned_p + ma_size + MALLOC_MINCHUNK))
    {
        /* allocated much more than what's required for padding, free
         * tail part */
        chunk * tail_chunk = (chunk *)(aligned_p + ma_size);
        chunk_p->size = aligned_p + ma_size - (char *)chunk_p;
        tail_chunk->size = size_allocated - chunk_p->size;
        nano_free(RCALL (char *)tail_chunk + CHUNK_OFFSET);
    }
    return aligned_p;
}
Esempio n. 5
0
/*
 * Read a Unicode line from a window. Called when the respective event
 * has been requested and is read.
 *
 * - win      the window the user must input the text
 * - buf      the buffer to store the input; may already contain text; *not*
 *            0-terminated
 * - maxlen   the lenght of the buffer
 * - initlen  the lenght of the initial text
 */
glui32 nanoglk_window_get_line_uni(winid_t win, glui32 *buf, glui32 maxlen,
                                   glui32 initlen)
{
   nano_trace("nanoglk_window_get_line_uni(%p, %p, %d, %d)",
              win, buf, maxlen, initlen);

   // Convert glui32* to Uint16* ...
   Uint16 *text = (Uint16*)nano_malloc((maxlen + 1) * sizeof(Uint16*));
   int i;
   for(i = 0; i < initlen; i++)
      text[i] = buf[i];
   text[initlen] = 0;

   // ... read Uint16* ...
   int len = get_line16(win, text, maxlen, 0xffff);

   // ... and convert it back to glui32*.
   for(i = 0; text[i]; i++)
      buf[i] = text[i];
  
   return len;
}
Esempio n. 6
0
/* Function nano_calloc
 * Implement calloc simply by calling malloc and set zero */
void * nano_calloc(RARG malloc_size_t n, malloc_size_t elem)
{
    void * mem = nano_malloc(RCALL n * elem);
    if (mem != NULL) memset(mem, 0, n * elem);
    return mem;
}
Esempio n. 7
0
frefid_t glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock)
{
   int must_exist = 0, warn_replace = 0, warn_modify = 0, warn_append = 0;
   char title8[128];

   switch(fmode) {
   case filemode_Read:
      strcpy(title8, "Read ");
      must_exist = 1;
      break;

   case filemode_Write:
      strcpy(title8, "Write (or replace) ");
      warn_replace = 1;
      break;
      
   case filemode_ReadWrite:
      strcpy(title8, "Write (or modify) ");
      warn_modify = 1;
      break;

   case filemode_WriteAppend:
      strcpy(title8, "Write (or append to) ");
      warn_append = 1;
      break;
   }

   switch(usage & fileusage_TypeMask) {
   case fileusage_Data:
      strcat(title8, "data");
      break;

   case fileusage_SavedGame:
      strcat(title8, "saved game");
      break;

   case fileusage_Transcript:
      strcat(title8, "transscript");
      break;

   case fileusage_InputRecord:
      strcat(title8, "input record file");
      break;
   }

   char cwd[FILENAME_MAX + 1];
   getcwd(cwd, FILENAME_MAX + 1);

   Uint16 *title16 = strdup16fromutf8(title8);
   char *name = 
      nano_input_file(cwd, title16, nanoglk_surface,
                      nanoglk_ui_font->font, nanoglk_ui_font->text_height,
                      nanoglk_ui_font->fg, nanoglk_ui_font->bg,
                      nanoglk_ui_list_i_fg_color, nanoglk_ui_list_i_bg_color,
                      nanoglk_ui_list_a_fg_color, nanoglk_ui_list_a_bg_color,
                      nanoglk_ui_input_fg_color, nanoglk_ui_input_bg_color,
                      (nanoglk_screen_width - nanoglk_filesel_width) / 2,
                      (nanoglk_screen_height - nanoglk_filesel_height) / 2,
                      nanoglk_filesel_width, nanoglk_filesel_height,
                      must_exist, warn_replace, warn_modify, warn_append);
   free(title16);
   // TODO change directory depending on the result?

   frefid_t fref = NULL;

   if(name) {
      fref = (frefid_t)nano_malloc(sizeof(struct glk_fileref_struct));
      fref->usage = usage;
      fref->rock = rock;
      fref->name = name;
      ADD(fref);
   }

   nanoglk_log("glk_fileref_create_by_prompt(%d, %d, %d) => %p",
               usage, fmode, rock, fref);
   if(fref)
      fref->disprock = nanoglk_call_regi_obj(fref, gidisp_Class_Fileref);

   return fref;
}
Esempio n. 8
0
winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
                        glui32 wintype, glui32 rock)
{
   winid_t win = (winid_t)nano_malloc(sizeof(struct glk_window_struct));
   nanoglk_log("glk_window_open(%p, %d, %d, %d, %d) => %p",
              split, method, size, wintype, rock, win);

   win->stream = nanoglk_stream_new(streamtype_Window, 0);
   win->stream->x.window = win;

   win->method = method;
   win->size = size;
   win->wintype = wintype;
   win->rock = rock;
   win->left = win->right = NULL;
   win->cur_styl = style_Normal;
   
   // Colors for styles. See comment at the beginning of this file.
   int i;
   switch(win->wintype) {
   case wintype_TextBuffer:
      for(i = 0; i < style_NUMSTYLES; i++) {
         win->fg[i] = next_buffer_fg[i];
         win->bg[i] = next_buffer_bg[i];
      }
      break;

   case wintype_TextGrid:
      for(i = 0; i < style_NUMSTYLES; i++) {
         win->fg[i] = next_grid_fg[i];
         win->bg[i] = next_grid_bg[i];
      }
      break;
   }

   winid_t pair;
   
   if(split == NULL) {
      // parent is NULL => new root window
      nano_failunless(root == NULL, "two root windows");

      win->parent = NULL;
      win->area.x = win->area.y = 0;
      win->area.w = nanoglk_surface->w;
      win->area.h = nanoglk_surface->h;

      root = win;

      pair = NULL; // no pair window created

      nano_trace("[glk_window_open] root %p: (%d, %d, %d x %d)",
                 win, win->area.x, win->area.y, win->area.w, win->area.h);
   } else {
      // Create a pair window. The old parent "split" becomes the left
      // child, the newly created becomes the right child. (See also
      // comment on these members in "nanoglk.h".)
      pair = (winid_t)nano_malloc(sizeof(struct glk_window_struct));
      pair->stream = NULL;
      pair->wintype = wintype_Pair;
      pair->rock = 0;
      pair->left = split;
      pair->right = win;
      pair->area = split->area;
      pair->method = split->method;
      pair->size = split->size;
      pair->parent = split->parent;

      // Rearrange tree: "pair" takes over the place of "split".
      if(pair->parent == NULL)
         root = pair;
      else {
         if(pair->parent->left == split)
            pair->parent->left = pair;
         else if(pair->parent->right == split)
            pair->parent->right = pair;
         else
            nano_fail("split not child of parent?");
      }

      split->parent = win->parent = pair;
      pair->left = split;
      pair->right = win;

      win->area = split->area;
      SDL_Rect split_area, win_area;
      window_calc_sizes(pair, &split_area, &win_area);
      window_resize(split, &split_area);
      win->area = win_area;

      window_draw_border(pair);

      nano_trace("split %p: (%d, %d, %d x %d)", split, split->area.x,
                split->area.y, split->area.w, split->area.h);
      nano_trace("new win %p: (%d, %d, %d x %d)", win, win->area.x,
                 win->area.y, win->area.w, win->area.h);
   }

   // Further initialization depending on the type.
   switch(win->wintype) {
   case wintype_TextBuffer:
      nanoglk_wintextbuffer_init(win);
      break;

   case wintype_TextGrid:
      nanoglk_wintextgrid_init(win);
      break;

   case wintype_Graphics:
      nanoglk_wingraphics_init(win);
      break;
   }

   if(pair)
      pair->disprock = nanoglk_call_regi_obj(pair, gidisp_Class_Window);

   win->stream->disprock
      = nanoglk_call_regi_obj(win->stream, gidisp_Class_Stream);
   win->disprock = nanoglk_call_regi_obj(win, gidisp_Class_Window);
   
   return win;
}