/* * Allocates memory for a 2-dimensional array of chars and returns a pointer * thereto. Each line is formed from a set of char arrays, with an index * (i.e., the ScrnBuf type). The first pointer in the index is reserved for * per-line flags, and does not point to data. * * After the per-line flags, we have a series of pointers to char arrays: The * first one is the actual character array, the second one is the attributes, * the third is the foreground and background colors, and the fourth denotes * the character set. * * We store it all as pointers, because of alignment considerations, together * with the intention of being able to change the total number of pointers per * row according to whether the user wants color or not. */ ScrnBuf Allocate(int nrow, int ncol, Char ** addr) { ScrnBuf base; Char *tmp; int i, j, k; size_t entries = MAX_PTRS * nrow; size_t length = BUF_PTRS * nrow * ncol; if ((base = TypeCallocN(ScrnPtr, entries)) == 0) SysError(ERROR_SCALLOC); if ((tmp = TypeCallocN(Char, length)) == 0) SysError(ERROR_SCALLOC2); *addr = tmp; for (i = k = 0; i < nrow; i++) { base[k] = 0; /* per-line flags */ k += BUF_HEAD; for (j = BUF_HEAD; j < MAX_PTRS; j++) { base[k++] = tmp; tmp += ncol; } } return (base); }
static CgsCache * allocCache(void **cache_pointer) { if (*cache_pointer == 0) { *cache_pointer = TypeCallocN(CgsCache, gcMAX); TRACE(("allocCache %p\n", *cache_pointer)); } return *((CgsCache **) cache_pointer); }
static Graphic * allocGraphic(int max_w, int max_h) { Graphic *result = TypeCalloc(Graphic); if (result) { result->max_width = max_w; result->max_height = max_h; if (!(result->pixels = TypeCallocN(RegisterNum, (size_t) max_w * (size_t) max_h))) { result = freeGraphic(result); } else if (!(result->private_color_registers = allocRegisters())) { result = freeGraphic(result); } } return result; }
static ColorRegister * allocRegisters(void) { return TypeCallocN(ColorRegister, MAX_COLOR_REGISTERS); }
/* * This function reallocates memory if changing the number of Buf offsets. * The code is based on Reallocate(). */ static void ReallocateBufOffsets(ScrnBuf * sbuf, Char ** sbufaddr, unsigned nrow, unsigned ncol, size_t new_max_offsets) { unsigned i; int j, k; ScrnBuf base; Char *oldbuf, *tmp; size_t entries, length; /* * As there are 2 buffers (allbuf, altbuf), we cannot change num_ptrs in * this function. However MAX_PTRS and BUF_PTRS depend on num_ptrs so * change it now and restore the value when done. */ int old_max_ptrs = MAX_PTRS; assert(nrow != 0); assert(ncol != 0); assert(new_max_offsets != 0); dump_screen("before", *sbuf, *sbufaddr, nrow, ncol); term->num_ptrs = new_max_offsets; entries = MAX_PTRS * nrow; length = BUF_PTRS * nrow * ncol; oldbuf = *sbufaddr; *sbuf = TypeRealloc(ScrnPtr, entries, *sbuf); if (*sbuf == 0) SysError(ERROR_RESIZE); base = *sbuf; if ((tmp = TypeCallocN(Char, length)) == 0) SysError(ERROR_SREALLOC); *sbufaddr = tmp; for (i = k = 0; i < nrow; i++) { k += BUF_HEAD; for (j = BUF_HEAD; j < old_max_ptrs; j++) { memcpy(tmp, base[k++], ncol); tmp += ncol; } tmp += ncol * (new_max_offsets - old_max_ptrs); } /* * update the pointers in sbuf */ for (i = k = 0, tmp = *sbufaddr; i < nrow; i++) { for (j = 0; j < BUF_HEAD; j++) base[k++] = 0; for (j = BUF_HEAD; j < MAX_PTRS; j++) { base[k++] = tmp; tmp += ncol; } } /* Now free the old buffer and restore num_ptrs */ free(oldbuf); dump_screen("after", *sbuf, *sbufaddr, nrow, ncol); term->num_ptrs = old_max_ptrs; }
/* * This is called when the screen is resized. * Returns the number of lines the text was moved down (neg for up). * (Return value only necessary with SouthWestGravity.) */ static int Reallocate(ScrnBuf * sbuf, Char ** sbufaddr, int nrow, int ncol, int oldrow, int oldcol) { ScrnBuf base; Char *tmp; int i, j, k, minrows; size_t mincols; Char *oldbuf; int move_down = 0, move_up = 0; size_t entries = MAX_PTRS * nrow; size_t length = BUF_PTRS * nrow * ncol; if (sbuf == NULL || *sbuf == NULL) { return 0; } oldbuf = *sbufaddr; /* * Special case if oldcol == ncol - straight forward realloc and * update of the additional lines in sbuf * * FIXME: this is a good idea, but doesn't seem to be implemented. * -gildea */ /* * realloc sbuf, the pointers to all the lines. * If the screen shrinks, remove lines off the top of the buffer * if resizeGravity resource says to do so. */ if (nrow < oldrow && term->misc.resizeGravity == SouthWestGravity) { /* Remove lines off the top of the buffer if necessary. */ move_up = (oldrow - nrow) - (term->screen.max_row - term->screen.cur_row); if (move_up < 0) move_up = 0; /* Overlapping memmove here! */ memmove(*sbuf, *sbuf + (move_up * MAX_PTRS), MAX_PTRS * (oldrow - move_up) * sizeof((*sbuf)[0])); } *sbuf = TypeRealloc(ScrnPtr, entries, *sbuf); if (*sbuf == 0) SysError(ERROR_RESIZE); base = *sbuf; /* * create the new buffer space and copy old buffer contents there * line by line. */ if ((tmp = TypeCallocN(Char, length)) == 0) SysError(ERROR_SREALLOC); *sbufaddr = tmp; minrows = (oldrow < nrow) ? oldrow : nrow; mincols = (oldcol < ncol) ? oldcol : ncol; if (nrow > oldrow && term->misc.resizeGravity == SouthWestGravity) { /* move data down to bottom of expanded screen */ move_down = Min(nrow - oldrow, term->screen.savedlines); tmp += (ncol * move_down * BUF_PTRS); } for (i = k = 0; i < minrows; i++) { k += BUF_HEAD; for (j = BUF_HEAD; j < MAX_PTRS; j++) { memcpy(tmp, base[k++], mincols); tmp += ncol; } } /* * update the pointers in sbuf */ for (i = k = 0, tmp = *sbufaddr; i < nrow; i++) { for (j = 0; j < BUF_HEAD; j++) base[k++] = 0; for (j = BUF_HEAD; j < MAX_PTRS; j++) { base[k++] = tmp; tmp += ncol; } } /* Now free the old buffer */ free(oldbuf); return move_down ? move_down : -move_up; /* convert to rows */ }