/* * This creates a new CDK screen. */ CDKSCREEN *initCDKScreen (WINDOW *window) { ALL_SCREENS *item; CDKSCREEN *screen = 0; /* initialization, for the first time */ if (all_screens == 0) { /* Set up basic curses settings. */ #ifdef HAVE_SETLOCALE setlocale (LC_ALL, ""); #endif noecho (); cbreak (); } if ((item = typeMalloc (ALL_SCREENS)) != 0) { if ((screen = typeCalloc (CDKSCREEN)) != 0) { item->link = all_screens; item->screen = screen; all_screens = item; /* Initialize the CDKSCREEN pointer. */ screen->objectCount = 0; screen->objectLimit = 2; screen->object = typeMallocN (CDKOBJS *, screen->objectLimit); screen->window = window; /* OK, we are done. */ } else {
link_fieldtype(FIELDTYPE *type1, FIELDTYPE *type2) { FIELDTYPE *nftyp = (FIELDTYPE *)0; T((T_CALLED("link_fieldtype(%p,%p)"), type1, type2)); if (type1 && type2) { nftyp = typeMalloc(FIELDTYPE, 1); if (nftyp) { T((T_CREATE("fieldtype %p"), nftyp)); *nftyp = *_nc_Default_FieldType; nftyp->status |= _LINKED_TYPE; if ((type1->status & _HAS_ARGS) || (type2->status & _HAS_ARGS)) nftyp->status |= _HAS_ARGS; if ((type1->status & _HAS_CHOICE) || (type2->status & _HAS_CHOICE)) nftyp->status |= _HAS_CHOICE; nftyp->left = type1; nftyp->right = type2; type1->ref++; type2->ref++; } else { SET_ERROR(E_SYSTEM_ERROR); } } else { SET_ERROR(E_BAD_ARGUMENT); } returnFieldType(nftyp); }
/*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Make_Enum_Type( va_list * ap ) | | Description : Allocate structure for enumeration type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * Make_Enum_Type(va_list *ap) { enumARG *argp = typeMalloc(enumARG, 1); if (argp) { int cnt = 0; char **kp = (char **)0; int ccase, cunique; T((T_CREATE("enumARG %p"), argp)); argp->kwds = va_arg(*ap, char **); ccase = va_arg(*ap, int); cunique = va_arg(*ap, int); argp->checkcase = ccase ? TRUE : FALSE; argp->checkunique = cunique ? TRUE : FALSE; kp = argp->kwds; while (kp && (*kp++)) cnt++; argp->count = cnt; } return (void *)argp; }
/*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Generic_This_Type(void * arg) | | Description : Allocate structure for numeric type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * Generic_This_Type(void *arg) { thisARG *argn = (thisARG *) 0; thisPARM *args = (thisPARM *) arg; if (args) { argn = typeMalloc(thisARG, 1); if (argn) { T((T_CREATE("thisARG %p"), (void *)argn)); argn->precision = args->precision; argn->low = args->low; argn->high = args->high; #if HAVE_LOCALE_H argn->L = localeconv(); #else argn->L = NULL; #endif } } return (void *)argn; }
NCURSES_SP_NAME(new_form) (NCURSES_SP_DCLx FIELD **fields) { int err = E_SYSTEM_ERROR; FORM *form = (FORM *)0; T((T_CALLED("new_form(%p,%p)"), (void *)SP_PARM, (void *)fields)); if (IsValidScreen(SP_PARM)) { form = typeMalloc(FORM, 1); if (form) { T((T_CREATE("form %p"), (void *)form)); *form = *_nc_Default_Form; /* This ensures win and sub are always non-null, so we can derive always the SCREEN that this form is running on. */ form->win = StdScreen(SP_PARM); form->sub = StdScreen(SP_PARM); if ((err = Associate_Fields(form, fields)) != E_OK) { free_form(form); form = (FORM *)0; } } } if (!form) SET_ERROR(err); returnForm(form); }
new_fieldtype(bool (*const field_check) (FIELD *, const void *), bool (*const char_check) (int, const void *)) { FIELDTYPE *nftyp = (FIELDTYPE *)0; T((T_CALLED("new_fieldtype(%p,%p)"), field_check, char_check)); if ((field_check) || (char_check)) { nftyp = typeMalloc(FIELDTYPE, 1); if (nftyp) { T((T_CREATE("fieldtype %p"), nftyp)); *nftyp = default_fieldtype; nftyp->fcheck = field_check; nftyp->ccheck = char_check; } else { SET_ERROR(E_SYSTEM_ERROR); } } else { SET_ERROR(E_BAD_ARGUMENT); } returnFieldType(nftyp); }
/* Create list. */ HTList *HTList_new(void) { HTList *newList; if ((newList = typeMalloc(HTList)) == NULL) outofmem(__FILE__, "HTList_new"); newList->object = NULL; newList->next = NULL; return newList; }
/*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Make_This_Type(va_list *ap) | | Description : Allocate structure for alphanumeric type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * Make_This_Type(va_list *ap) { thisARG *argp = typeMalloc(thisARG, 1); if (argp) { T((T_CREATE("thisARG %p"), argp)); argp->width = va_arg(*ap, int); } return ((void *)argp); }
/*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Copy_ThisType(const void *argp) | | Description : Copy structure for alphanumeric type argument. | | Return Values : Pointer to argument structure or NULL on error. +--------------------------------------------------------------------------*/ static void * Copy_This_Type(const void *argp) { const thisARG *ap = (const thisARG *)argp; thisARG *result = typeMalloc(thisARG, 1); if (result) { T((T_CREATE("thisARG %p"), result)); *result = *ap; } return ((void *)result); }
/*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Make_This_Type( va_list * ap ) | | Description : Allocate structure for integer type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * Make_This_Type(va_list *ap) { thisARG *argp = typeMalloc(thisARG, 1); if (argp) { T((T_CREATE("thisARG %p"), argp)); argp->precision = va_arg(*ap, int); argp->low = va_arg(*ap, long); argp->high = va_arg(*ap, long); } return (void *)argp; }
dup_field(FIELD *field, int frow, int fcol) { FIELD *New_Field = (FIELD *)0; int err = E_BAD_ARGUMENT; T((T_CALLED("dup_field(%p,%d,%d)"), (void *)field, frow, fcol)); if (field && (frow >= 0) && (fcol >= 0) && ((err = E_SYSTEM_ERROR) != 0) && /* trick : this resets the default error */ (New_Field = typeMalloc(FIELD, 1))) { T((T_CREATE("field %p"), (void *)New_Field)); *New_Field = *_nc_Default_Field; New_Field->frow = (short) frow; New_Field->fcol = (short) fcol; New_Field->link = New_Field; New_Field->rows = field->rows; New_Field->cols = field->cols; New_Field->nrow = field->nrow; New_Field->drows = field->drows; New_Field->dcols = field->dcols; New_Field->maxgrow = field->maxgrow; New_Field->nbuf = field->nbuf; New_Field->just = field->just; New_Field->fore = field->fore; New_Field->back = field->back; New_Field->pad = field->pad; New_Field->opts = field->opts; New_Field->usrptr = field->usrptr; if (_nc_Copy_Type(New_Field, field)) { size_t i, len; len = Total_Buffer_Size(New_Field); if ((New_Field->buf = (FIELD_CELL *)malloc(len))) { for (i = 0; i < len; ++i) New_Field->buf[i] = field->buf[i]; returnField(New_Field); } } } if (New_Field) free_field(New_Field); SET_ERROR(err); returnField((FIELD *)0); }
/*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Make_RegularExpression_Type(va_list * ap) | | Description : Allocate structure for regex type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * Make_RegularExpression_Type(va_list *ap) { #if HAVE_REGEX_H_FUNCS char *rx = va_arg(*ap, char *); RegExp_Arg *preg; preg = typeMalloc(RegExp_Arg, 1); if (preg) { T((T_CREATE("RegExp_Arg %p"), preg)); if (((preg->pRegExp = typeMalloc(regex_t, 1)) != 0) && !regcomp(preg->pRegExp, rx, (REG_EXTENDED | REG_NOSUB | REG_NEWLINE))) { T((T_CREATE("regex_t %p"), preg->pRegExp)); preg->refCount = typeMalloc(unsigned long, 1); *(preg->refCount) = 1; } else { if (preg->pRegExp)
/*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Generic_This_Type(va_list *ap) | | Description : Allocate structure for alpha type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * Generic_This_Type(void *arg) { thisARG *argp = (thisARG *) 0; if (arg) { argp = typeMalloc(thisARG, 1); if (argp) { T((T_CREATE("thisARG %p"), (void *)argp)); argp->width = *((int *)arg); } } return ((void *)argp); }
/* Add object to START of list (so it is pointed to by the head). */ void HTList_addObject(HTList *me, void *newObject) { HTList *newNode; if (me) { if ((newNode = typeMalloc(HTList)) == NULL) outofmem(__FILE__, "HTList_addObject"); newNode->object = newObject; newNode->next = me->next; me->next = newNode; } else { CTRACE((tfp, "HTList: Trying to add object %p to a nonexisting list\n", newObject)); } return; }
/*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Copy_Enum_Type( const void * argp ) | | Description : Copy structure for enumeration type argument. | | Return Values : Pointer to argument structure or NULL on error. +--------------------------------------------------------------------------*/ static void * Copy_Enum_Type(const void *argp) { enumARG *result = (enumARG *)0; if (argp) { const enumARG *ap = (const enumARG *)argp; result = typeMalloc(enumARG, 1); if (result) { T((T_CREATE("enumARG %p"), result)); *result = *ap; } } return (void *)result; }
/*--------------------------------------------------------------------------- | Facility : libnform | Function : static TypeArgument *GenericArgument( | const FIELDTYPE* typ, | int (*argiterator)(void**), | int* err) | | Description : The iterator callback must browse through all fieldtype | parameters that have an argument associated with the | type. The iterator returns 1 if the operation to get | the next element was successfull, 0 otherwise. If the | iterator could move to the next argument, it fills | the void* pointer representing the argument into the | location provided as argument to the iterator. | The err reference is used to keep track of errors. | | Return Values : Pointer to argument structure +--------------------------------------------------------------------------*/ static TypeArgument * GenericArgument(const FIELDTYPE *typ, int (*argiterator) (void **), int *err) { TypeArgument *res = (TypeArgument *)0; if (typ != 0 && (typ->status & _HAS_ARGS) != 0 && err != 0 && argiterator != 0) { if (typ->status & _LINKED_TYPE) { /* Composite fieldtypes keep track internally of their own memory */ TypeArgument *p = typeMalloc(TypeArgument, 1); if (p) { p->left = GenericArgument(typ->left, argiterator, err); p->right = GenericArgument(typ->right, argiterator, err); return p; } else *err += 1; } else { assert(typ->genericarg != (void *)0); if (typ->genericarg == 0) *err += 1; else { void *argp; int valid = argiterator(&argp); if (valid == 0 || argp == 0 || !(res = (TypeArgument *)typ->genericarg(argp))) { *err += 1; } } } } return res; }
/* Insert an object into the list at a specified position. * If position is 0, this places the object at the head of the list * and is equivalent to HTList_addObject(). */ void HTList_insertObjectAt(HTList *me, void *newObject, int pos) { HTList *newNode; HTList *temp = me; HTList *prevNode; int Pos = pos; if (!temp) { CTRACE((tfp, "HTList: Trying to add object %p to a nonexisting list\n", newObject)); return; } if (Pos < 0) { Pos = 0; CTRACE((tfp, "HTList: Treating negative object position %d as %d.\n", pos, Pos)); } prevNode = temp; while ((temp = temp->next)) { if (Pos == 0) { if ((newNode = typeMalloc(HTList)) == NULL) outofmem(__FILE__, "HTList_addObjectAt"); assert(newNode != NULL); newNode->object = newObject; newNode->next = temp; if (prevNode) prevNode->next = newNode; return; } prevNode = temp; Pos--; } if (Pos >= 0) HTList_addObject(prevNode, newObject); return; }
_nc_generic_fieldtype(bool (*const field_check) (FORM *, FIELD *, const void *), bool (*const char_check) (int, FORM *, FIELD *, const void *), bool (*const next) (FORM *, FIELD *, const void *), bool (*const prev) (FORM *, FIELD *, const void *), void (*freecallback) (void *)) { int code = E_SYSTEM_ERROR; FIELDTYPE *res = (FIELDTYPE *)0; T((T_CALLED("_nc_generic_fieldtype(%p,%p,%p,%p,%p)"), field_check, char_check, next, prev, freecallback)); if (field_check || char_check) { res = typeMalloc(FIELDTYPE, 1); if (res) { *res = *_nc_Default_FieldType; res->status |= (_HAS_ARGS | _GENERIC); res->fieldcheck.gfcheck = field_check; res->charcheck.gccheck = char_check; res->genericarg = Generic_This_Type; res->freearg = freecallback; res->enum_next.gnext = next; res->enum_prev.gprev = prev; code = E_OK; } } else code = E_BAD_ARGUMENT; if (E_OK != code) SET_ERROR(code); returnFieldType(res); }
new_form(FIELD **fields) { int err = E_SYSTEM_ERROR; FORM *form = typeMalloc(FORM, 1); T((T_CALLED("new_form(%p)"), fields)); if (form) { T((T_CREATE("form %p"), form)); *form = *_nc_Default_Form; if ((err = Associate_Fields(form, fields)) != E_OK) { free_form(form); form = (FORM *)0; } } if (!form) SET_ERROR(err); returnForm(form); }
_nc_resolve_uses2(bool fullresolve, bool literal) /* try to resolve all use capabilities */ { ENTRY *qp, *rp, *lastread = 0; bool keepgoing; unsigned i; int unresolved, total_unresolved, multiples; DEBUG(2, ("RESOLUTION BEGINNING")); /* * Check for multiple occurrences of the same name. */ multiples = 0; for_entry_list(qp) { int matchcount = 0; for_entry_list(rp) { if (qp > rp && _nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) { matchcount++; if (matchcount == 1) { (void) fprintf(stderr, "Name collision between %s", _nc_first_name(qp->tterm.term_names)); multiples++; } if (matchcount >= 1) (void) fprintf(stderr, " %s", _nc_first_name(rp->tterm.term_names)); } } if (matchcount >= 1) (void) putc('\n', stderr); } if (multiples > 0) return (FALSE); DEBUG(2, ("NO MULTIPLE NAME OCCURRENCES")); /* * First resolution stage: compute link pointers corresponding to names. */ total_unresolved = 0; _nc_curr_col = -1; for_entry_list(qp) { unresolved = 0; for (i = 0; i < qp->nuses; i++) { bool foundit; char *child = _nc_first_name(qp->tterm.term_names); char *lookfor = qp->uses[i].name; long lookline = qp->uses[i].line; foundit = FALSE; _nc_set_type(child); /* first, try to resolve from in-core records */ for_entry_list(rp) { if (rp != qp && _nc_name_match(rp->tterm.term_names, lookfor, "|")) { DEBUG(2, ("%s: resolving use=%s (in core)", child, lookfor)); qp->uses[i].link = rp; foundit = TRUE; } } /* if that didn't work, try to merge in a compiled entry */ if (!foundit) { TERMTYPE thisterm; char filename[PATH_MAX]; memset(&thisterm, 0, sizeof(thisterm)); if (_nc_read_entry(lookfor, filename, &thisterm) == 1) { DEBUG(2, ("%s: resolving use=%s (compiled)", child, lookfor)); rp = typeMalloc(ENTRY, 1); if (rp == 0) _nc_err_abort(MSG_NO_MEMORY); rp->tterm = thisterm; rp->nuses = 0; rp->next = lastread; lastread = rp; qp->uses[i].link = rp; foundit = TRUE; } } /* no good, mark this one unresolvable and complain */ if (!foundit) { unresolved++; total_unresolved++; _nc_curr_line = lookline; _nc_warning("resolution of use=%s failed", lookfor); qp->uses[i].link = 0; } } } if (total_unresolved) { /* free entries read in off disk */ _nc_free_entries(lastread); return (FALSE); } DEBUG(2, ("NAME RESOLUTION COMPLETED OK")); /* * OK, at this point all (char *) references in `name' members * have been successfully converted to (ENTRY *) pointers in * `link' members. Time to do the actual merges. */ if (fullresolve) { do { TERMTYPE merged; keepgoing = FALSE; for_entry_list(qp) { if (qp->nuses > 0) { DEBUG(2, ("%s: attempting merge", _nc_first_name(qp->tterm.term_names))); /* * If any of the use entries we're looking for is * incomplete, punt. We'll catch this entry on a * subsequent pass. */ for (i = 0; i < qp->nuses; i++) if (qp->uses[i].link->nuses) { DEBUG(2, ("%s: use entry %d unresolved", _nc_first_name(qp->tterm.term_names), i)); goto incomplete; } /* * First, make sure there is no garbage in the * merge block. As a side effect, copy into * the merged entry the name field and string * table pointer. */ _nc_copy_termtype(&merged, &(qp->tterm)); /* * Now merge in each use entry in the proper * (reverse) order. */ for (; qp->nuses; qp->nuses--) _nc_merge_entry(&merged, &qp->uses[qp->nuses - 1].link->tterm); /* * Now merge in the original entry. */ _nc_merge_entry(&merged, &qp->tterm); /* * Replace the original entry with the merged one. */ FreeIfNeeded(qp->tterm.Booleans); FreeIfNeeded(qp->tterm.Numbers); FreeIfNeeded(qp->tterm.Strings); #if NCURSES_XNAMES FreeIfNeeded(qp->tterm.ext_Names); #endif qp->tterm = merged; _nc_wrap_entry(qp, TRUE); /* * We know every entry is resolvable because name resolution * didn't bomb. So go back for another pass. */ /* FALLTHRU */ incomplete: keepgoing = TRUE; } } } while (keepgoing); DEBUG(2, ("MERGES COMPLETED OK")); } /* * We'd like to free entries read in off disk at this point, but can't. * The merge_entry() code doesn't copy the strings in the use entries, * it just aliases them. If this ever changes, do a * free_entries(lastread) here. */ DEBUG(2, ("RESOLUTION FINISHED")); if (fullresolve) if (_nc_check_termtype != 0) { _nc_curr_col = -1; for_entry_list(qp) { _nc_curr_line = qp->startline; _nc_set_type(_nc_first_name(qp->tterm.term_names)); _nc_check_termtype2(&qp->tterm, literal); } DEBUG(2, ("SANITY CHECK FINISHED")); }
/* * Syntax for -m: * [port-type][test baudrate]:terminal-type * The baud rate tests are: >, <, @, =, ! */ static void add_mapping(const char *port, char *arg) { MAP *mapp; char *copy, *p; const char *termp; char *base = 0; copy = strdup(arg); mapp = typeMalloc(MAP, 1); if (copy == 0 || mapp == 0) failed("malloc"); assert(copy != 0); assert(mapp != 0); mapp->next = 0; if (maplist == 0) cur = maplist = mapp; else { cur->next = mapp; cur = mapp; } mapp->porttype = arg; mapp->conditional = 0; arg = strpbrk(arg, "><@=!:"); if (arg == 0) { /* [?]term */ mapp->type = mapp->porttype; mapp->porttype = 0; goto done; } if (arg == mapp->porttype) /* [><@=! baud]:term */ termp = mapp->porttype = 0; else termp = base = arg; for (;; ++arg) { /* Optional conditionals. */ switch (*arg) { case '<': if (mapp->conditional & GT) goto badmopt; mapp->conditional |= LT; break; case '>': if (mapp->conditional & LT) goto badmopt; mapp->conditional |= GT; break; case '@': case '=': /* Not documented. */ mapp->conditional |= EQ; break; case '!': mapp->conditional |= NOT; break; default: goto next; } } next: if (*arg == ':') { if (mapp->conditional) goto badmopt; ++arg; } else { /* Optional baudrate. */ arg = strchr(p = arg, ':'); if (arg == 0) goto badmopt; *arg++ = '\0'; mapp->speed = tbaudrate(p); } mapp->type = arg; /* Terminate porttype, if specified. */ if (termp != 0) *base = '\0'; /* If a NOT conditional, reverse the test. */ if (mapp->conditional & NOT) mapp->conditional = ~mapp->conditional & (EQ | GT | LT); /* If user specified a port with an option flag, set it. */ done: if (port) { if (mapp->porttype) { badmopt: err("illegal -m option format: %s", copy); } mapp->porttype = port; } free(copy); #ifdef MAPDEBUG (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY"); (void) printf("type: %s\n", mapp->type); (void) printf("conditional: "); p = ""; if (mapp->conditional & GT) { (void) printf("GT"); p = "/"; } if (mapp->conditional & EQ) { (void) printf("%sEQ", p); p = "/"; } if (mapp->conditional & LT) (void) printf("%sLT", p); (void) printf("\nspeed: %d\n", mapp->speed); #endif }
_nc_hash_map(void) { HASHMAP *sp; register int i; int start, shift, size; if (screen_lines > lines_alloc) { if (hashtab) free(hashtab); hashtab = typeMalloc(HASHMAP, (screen_lines + 1) * 2); if (!hashtab) { if (oldhash) { FreeAndNull(oldhash); } lines_alloc = 0; return; } lines_alloc = screen_lines; } if (oldhash && newhash) { /* re-hash only changed lines */ for (i = 0; i < screen_lines; i++) { if (PENDING(i)) newhash[i] = hash(NEWTEXT(i)); } } else { /* re-hash all */ if (oldhash == 0) oldhash = typeCalloc(unsigned long, (unsigned) screen_lines); if (newhash == 0) newhash = typeCalloc(unsigned long, (unsigned) screen_lines); if (!oldhash || !newhash) return; /* malloc failure */ for (i = 0; i < screen_lines; i++) { newhash[i] = hash(NEWTEXT(i)); oldhash[i] = hash(OLDTEXT(i)); } } #ifdef HASH_VERIFY for (i = 0; i < screen_lines; i++) { if (newhash[i] != hash(NEWTEXT(i))) fprintf(stderr, "error in newhash[%d]\n", i); if (oldhash[i] != hash(OLDTEXT(i))) fprintf(stderr, "error in oldhash[%d]\n", i); } #endif /* * Set up and count line-hash values. */ memset(hashtab, '\0', sizeof(*hashtab) * (screen_lines + 1) * 2); for (i = 0; i < screen_lines; i++) { unsigned long hashval = oldhash[i]; for (sp = hashtab; sp->hashval; sp++) if (sp->hashval == hashval) break; sp->hashval = hashval; /* in case this is a new entry */ sp->oldcount++; sp->oldindex = i; } for (i = 0; i < screen_lines; i++) { unsigned long hashval = newhash[i]; for (sp = hashtab; sp->hashval; sp++) if (sp->hashval == hashval) break; sp->hashval = hashval; /* in case this is a new entry */ sp->newcount++; sp->newindex = i; OLDNUM(i) = _NEWINDEX; /* initialize old indices array */ } /* * Mark line pairs corresponding to unique hash pairs. * * We don't mark lines with offset 0, because it can make fail * extending hunks by cost_effective. Otherwise, it does not * have any side effects. */ for (sp = hashtab; sp->hashval; sp++) if (sp->oldcount == 1 && sp->newcount == 1 && sp->oldindex != sp->newindex) { TR(TRACE_UPDATE | TRACE_MOVE, ("new line %d is hash-identical to old line %d (unique)", sp->newindex, sp->oldindex)); OLDNUM(sp->newindex) = sp->oldindex; } grow_hunks(); /* * Eliminate bad or impossible shifts -- this includes removing * those hunks which could not grow because of conflicts, as well * those which are to be moved too far, they are likely to destroy * more than carry. */ for (i = 0; i < screen_lines;) { while (i < screen_lines && OLDNUM(i) == _NEWINDEX) i++; if (i >= screen_lines) break; start = i; shift = OLDNUM(i) - i; i++; while (i < screen_lines && OLDNUM(i) != _NEWINDEX && OLDNUM(i) - i == shift) i++; size = i - start; if (size < 3 || size + min(size / 8, 2) < abs(shift)) { while (start < i) { OLDNUM(start) = _NEWINDEX; start++; } } } /* After clearing invalid hunks, try grow the rest. */ grow_hunks(); }
wresize(WINDOW *win, int ToLines, int ToCols) { int col, row, size_x, size_y; struct ldat *pline; struct ldat *new_lines = 0; #ifdef TRACE T((T_CALLED("wresize(%p,%d,%d)"), win, ToLines, ToCols)); if (win) { TR(TRACE_UPDATE, ("...beg (%ld, %ld), max(%ld,%ld), reg(%ld,%ld)", (long) win->_begy, (long) win->_begx, (long) win->_maxy, (long) win->_maxx, (long) win->_regtop, (long) win->_regbottom)); if (USE_TRACEF(TRACE_UPDATE)) { _tracedump("...before", win); _nc_unlock_global(tracef); } } #endif if (!win || --ToLines < 0 || --ToCols < 0) returnCode(ERR); size_x = win->_maxx; size_y = win->_maxy; if (ToLines == size_y && ToCols == size_x) returnCode(OK); if ((win->_flags & _SUBWIN)) { /* * Check if the new limits will fit into the parent window's size. If * not, do not resize. We could adjust the location of the subwindow, * but the application may not like that. */ if (win->_pary + ToLines > win->_parent->_maxy || win->_parx + ToCols > win->_parent->_maxx) { returnCode(ERR); } pline = win->_parent->_line; } else { pline = 0; } /* * Allocate new memory as needed. Do the allocations without modifying * the original window, in case an allocation fails. Always allocate * (at least temporarily) the array pointing to the individual lines. */ new_lines = typeCalloc(struct ldat, (unsigned) (ToLines + 1)); if (new_lines == 0) returnCode(ERR); /* * For each line in the target, allocate or adjust pointers for the * corresponding text, depending on whether this is a window or a * subwindow. */ for (row = 0; row <= ToLines; ++row) { int begin = (row > size_y) ? 0 : (size_x + 1); int end = ToCols; NCURSES_CH_T *s; if (!(win->_flags & _SUBWIN)) { if (row <= size_y) { if (ToCols != size_x) { if ((s = typeMalloc(NCURSES_CH_T, ToCols + 1)) == 0) returnCode(cleanup_lines(new_lines, row)); for (col = 0; col <= ToCols; ++col) { s[col] = (col <= size_x ? win->_line[row].text[col] : win->_nc_bkgd); } } else { s = win->_line[row].text; } } else { if ((s = typeMalloc(NCURSES_CH_T, ToCols + 1)) == 0) returnCode(cleanup_lines(new_lines, row)); for (col = 0; col <= ToCols; ++col) s[col] = win->_nc_bkgd; } } else { s = &pline[win->_pary + row].text[win->_parx]; } if_USE_SCROLL_HINTS(new_lines[row].oldindex = row); if (row <= size_y) { new_lines[row].firstchar = win->_line[row].firstchar; new_lines[row].lastchar = win->_line[row].lastchar; } if ((ToCols != size_x) || (row > size_y)) { if (end >= begin) { /* growing */ if (new_lines[row].firstchar < begin) new_lines[row].firstchar = begin; } else { /* shrinking */ new_lines[row].firstchar = 0; } new_lines[row].lastchar = ToCols; } new_lines[row].text = s; } /* * Dispose of unwanted memory. */ if (!(win->_flags & _SUBWIN)) { if (ToCols == size_x) { for (row = ToLines + 1; row <= size_y; row++) { free(win->_line[row].text); } } else { for (row = 0; row <= size_y; row++) { free(win->_line[row].text); } } } free(win->_line); win->_line = new_lines; /* * Finally, adjust the parameters showing screen size and cursor * position: */ win->_maxx = ToCols; win->_maxy = ToLines; if (win->_regtop > win->_maxy) win->_regtop = win->_maxy; if (win->_regbottom > win->_maxy || win->_regbottom == size_y) win->_regbottom = win->_maxy; if (win->_curx > win->_maxx) win->_curx = win->_maxx; if (win->_cury > win->_maxy) win->_cury = win->_maxy; /* * Check for subwindows of this one, and readjust pointers to our text, * if needed. */ repair_subwindows(win); #ifdef TRACE TR(TRACE_UPDATE, ("...beg (%ld, %ld), max(%ld,%ld), reg(%ld,%ld)", (long) win->_begy, (long) win->_begx, (long) win->_maxy, (long) win->_maxx, (long) win->_regtop, (long) win->_regbottom)); if (USE_TRACEF(TRACE_UPDATE)) { _tracedump("...after:", win); _nc_unlock_global(tracef); } #endif returnCode(OK); }
/*--------------------------------------------------------------------------- | Facility : libnform | Function : static int Connect_Fields(FORM *form, FIELD **fields) | | Description : Set association between form and array of fields. | | Return Values : E_OK - no error | E_CONNECTED - a field is already connected | E_BAD_ARGUMENT - Invalid form pointer or field array | E_SYSTEM_ERROR - not enough memory +--------------------------------------------------------------------------*/ static int Connect_Fields(FORM *form, FIELD **fields) { int field_cnt, j; int page_nr; int maximum_row_in_field, maximum_col_in_field; _PAGE *pg; T((T_CALLED("Connect_Fields(%p,%p)"), (void *)form, (void *)fields)); assert(form); form->field = fields; form->maxfield = 0; form->maxpage = 0; if (!fields) RETURN(E_OK); page_nr = 0; /* store formpointer in fields and count pages */ for (field_cnt = 0; fields[field_cnt]; field_cnt++) { if (fields[field_cnt]->form) RETURN(E_CONNECTED); if (field_cnt == 0 || (fields[field_cnt]->status & _NEWPAGE)) page_nr++; fields[field_cnt]->form = form; } if (field_cnt == 0 || (short)field_cnt < 0) RETURN(E_BAD_ARGUMENT); /* allocate page structures */ if ((pg = typeMalloc(_PAGE, page_nr)) != (_PAGE *) 0) { T((T_CREATE("_PAGE %p"), (void *)pg)); form->page = pg; } else RETURN(E_SYSTEM_ERROR); /* Cycle through fields and calculate page boundaries as well as size of the form */ for (j = 0; j < field_cnt; j++) { if (j == 0) pg->pmin = (short) j; else { if (fields[j]->status & _NEWPAGE) { pg->pmax = (short) (j - 1); pg++; pg->pmin = (short) j; } } maximum_row_in_field = fields[j]->frow + fields[j]->rows; maximum_col_in_field = fields[j]->fcol + fields[j]->cols; if (form->rows < maximum_row_in_field) form->rows = (short) maximum_row_in_field; if (form->cols < maximum_col_in_field) form->cols = (short) maximum_col_in_field; } pg->pmax = (short) (field_cnt - 1); form->maxfield = (short) field_cnt; form->maxpage = (short) page_nr; /* Sort fields on form pages */ for (page_nr = 0; page_nr < form->maxpage; page_nr++) { FIELD *fld = (FIELD *)0; for (j = form->page[page_nr].pmin; j <= form->page[page_nr].pmax; j++) { fields[j]->index = (short) j; fields[j]->page = (short) page_nr; fld = Insert_Field_By_Position(fields[j], fld); } if (fld) { form->page[page_nr].smin = fld->index; form->page[page_nr].smax = fld->sprev->index; } else { form->page[page_nr].smin = 0; form->page[page_nr].smax = 0; } } RETURN(E_OK); }