Lines Matching defs:glh

118 static GlhHashBucket *glh_find_bucket(GlHistory *glh, const char *line,
201 static int _glh_cant_load_history(GlHistory *glh, const char *filename,
203 static int _glh_cant_save_history(GlHistory *glh, const char *message,
208 static void _glh_discard_line(GlHistory *glh, GlhLineNode *node);
209 static GlhLineNode *_glh_find_id(GlHistory *glh, GlhLineID id);
210 static GlhHashNode *_glh_acquire_copy(GlHistory *glh, const char *line,
212 static GlhHashNode *_glh_discard_copy(GlHistory *glh, GlhHashNode *hnode);
213 static int _glh_prepare_for_recall(GlHistory *glh, char *line);
252 GlHistory *glh; /* The object to be returned */
257 glh = (GlHistory *) malloc(sizeof(GlHistory));
258 if(!glh) {
267 glh->err = NULL;
268 glh->buffer = NULL;
269 glh->nbuff = (buflen+GLH_SEG_SIZE-1) / GLH_SEG_SIZE;
270 glh->unused = NULL;
271 glh->list.node_mem = NULL;
272 glh->list.head = glh->list.tail = NULL;
273 glh->recall = NULL;
274 glh->id_node = NULL;
275 glh->hash.node_mem = NULL;
277 glh->hash.bucket[i].lines = NULL;
278 glh->prefix = NULL;
279 glh->lbuf = NULL;
280 glh->lbuf_dim = 0;
281 glh->nbusy = 0;
282 glh->nfree = glh->nbuff;
283 glh->seq = 0;
284 glh->group = 0;
285 glh->nline = 0;
286 glh->max_lines = -1;
287 glh->enable = 1;
291 glh->err = _new_ErrMsg();
292 if(!glh->err)
293 return _del_GlHistory(glh);
297 if(glh->nbuff > 0) {
298 glh->nbuff = glh->nfree;
299 glh->buffer = (GlhLineSeg *) malloc(sizeof(GlhLineSeg) * glh->nbuff);
300 if(!glh->buffer) {
302 return _del_GlHistory(glh);
306 * a list and make glh->unused point to the head of this list.
308 glh->unused = glh->buffer;
309 for(i=0; i<glh->nbuff-1; i++) {
310 GlhLineSeg *seg = glh->unused + i;
313 glh->unused[i].next = NULL;
318 glh->list.node_mem = _new_FreeList(sizeof(GlhLineNode), GLH_LINE_INCR);
319 if(!glh->list.node_mem)
320 return _del_GlHistory(glh);
324 glh->hash.node_mem = _new_FreeList(sizeof(GlhLineNode), GLH_HASH_INCR);
325 if(!glh->hash.node_mem)
326 return _del_GlHistory(glh);
331 glh->lbuf_dim = GLH_LBUF_SIZE;
332 glh->lbuf = (char *) malloc(glh->lbuf_dim);
333 if(!glh->lbuf) {
335 return _del_GlHistory(glh);
337 return glh;
344 * glh GlHistory * The object to be deleted.
348 GlHistory *_del_GlHistory(GlHistory *glh)
350 if(glh) {
354 glh->err = _del_ErrMsg(glh->err);
358 if(glh->buffer) {
359 free(glh->buffer);
360 glh->buffer = NULL;
361 glh->unused = NULL;
366 glh->list.node_mem = _del_FreeList(glh->list.node_mem, 1);
370 glh->list.head = NULL;
371 glh->list.tail = NULL;
375 glh->hash.node_mem = _del_FreeList(glh->hash.node_mem, 1);
379 if(glh->lbuf)
380 free(glh->lbuf);
384 free(glh);
394 * glh GlHistory * The input-line history maintenance object.
403 int _glh_add_history(GlHistory *glh, const char *line, int force)
414 if(!glh || !line) {
421 if(!glh->enable || !glh->buffer || glh->max_lines == 0)
426 if(_glh_cancel_search(glh))
453 if(glh->max_lines >= 0) {
458 while(glh->nline > 0 && glh->nline >= glh->max_lines)
459 _glh_discard_line(glh, glh->list.head);
464 if(glh->max_lines == 0)
471 hnode = _glh_acquire_copy(glh, line, slen);
473 _err_record_msg(glh->err, "No room to store history line", END_ERR_MSG);
480 lnode = (GlhLineNode *) _new_FreeListNode(glh->list.node_mem);
486 hnode = _glh_discard_copy(glh, hnode);
487 _err_record_msg(glh->err, "No room to store history line", END_ERR_MSG);
495 lnode->id = glh->seq++;
497 lnode->group = glh->group;
502 if(glh->list.head)
503 glh->list.tail->next = lnode;
505 glh->list.head = lnode;
507 lnode->prev = glh->list.tail;
508 glh->list.tail = lnode;
512 glh->nline++;
521 * glh GlHistory * The input-line history maintenance object.
530 char *_glh_find_backwards(GlHistory *glh, char *line, size_t dim)
537 if(!glh || !line) {
538 if(glh)
539 _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG);
546 if(!glh->enable || !glh->buffer || glh->max_lines == 0)
552 _err_record_msg(glh->err, "'dim' argument inconsistent with strlen(line)",
560 if(_glh_prepare_for_recall(glh, line))
565 if(glh->recall) {
566 node = glh->recall->prev;
567 old_line = glh->recall->line;
569 node = glh->list.tail;
576 while(node && (node->group != glh->group || node->line == old_line ||
577 !_glh_line_matches_prefix(node->line, glh->prefix)))
587 glh->recall = node;
608 * glh GlHistory * The input-line history maintenance object.
618 char *_glh_find_forwards(GlHistory *glh, char *line, size_t dim)
625 if(!glh || !line) {
626 if(glh)
627 _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG);
634 if(!glh->enable || !glh->buffer || glh->max_lines == 0)
640 _err_record_msg(glh->err, "'dim' argument inconsistent with strlen(line)",
648 if(glh->recall) {
649 node = glh->recall->next;
650 old_line = glh->recall->line;
658 while(node && (node->group != glh->group || node->line == old_line ||
659 !_glh_line_matches_prefix(node->line, glh->prefix)))
672 glh->recall = node;
677 if(node == glh->list.tail)
678 _glh_cancel_search(glh);
698 * glh GlHistory * The input-line history maintenance object.
703 int _glh_cancel_search(GlHistory *glh)
708 if(!glh) {
715 if(!glh->recall)
719 * glh->recall to NULL before calling _glh_discard_line(), to avoid an
722 glh->recall = NULL;
726 _glh_discard_line(glh, glh->list.tail);
734 * glh GlHistory * The input-line history maintenance object.
741 int _glh_search_prefix(GlHistory *glh, const char *line, int prefix_len)
746 if(!glh) {
753 if(!glh->enable || !glh->buffer || glh->max_lines == 0)
758 glh->prefix = _glh_discard_copy(glh, glh->prefix);
766 glh->prefix = _glh_acquire_copy(glh, line, prefix_len);
770 if(!glh->prefix) {
771 _err_record_msg(glh->err, "The search prefix is too long to store",
784 * glh GlHistory * The input-line history maintenance object.
792 char *_glh_oldest_line(GlHistory *glh, char *line, size_t dim)
798 if(!glh || !line) {
799 if(glh)
800 _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG);
807 if(!glh->enable || !glh->buffer || glh->max_lines == 0)
813 _err_record_msg(glh->err, "'dim' argument inconsistent with strlen(line)",
821 if(_glh_prepare_for_recall(glh, line))
826 for(node=glh->list.head; node && node->group != glh->group;
838 glh->recall = node;
847 if(node == glh->list.tail)
848 _glh_cancel_search(glh);
856 * glh GlHistory * The input-line history maintenance object.
865 char *_glh_current_line(GlHistory *glh, char *line, size_t dim)
870 if(!glh || !line) {
871 if(glh)
872 _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG);
880 if(!glh->enable || !glh->buffer || glh->max_lines == 0 || !glh->recall)
886 _err_record_msg(glh->err, "'dim' argument inconsistent with strlen(line)",
894 _glh_return_line(glh->list.tail->line, line, dim);
898 _glh_cancel_search(glh);
909 * glh GlHistory * The input-line history maintenance object.
917 GlhLineID _glh_line_id(GlHistory *glh, int offset)
923 if(!glh->enable || !glh->buffer || glh->max_lines == 0)
929 for(node=glh->recall; node && offset != 0; node=node->next) {
930 if(node->group == glh->group)
934 for(node=glh->recall; node && offset != 0; node=node->prev) {
935 if(node->group == glh->group)
947 * glh GlHistory * The input-line history maintenance object.
956 char *_glh_recall_line(GlHistory *glh, GlhLineID id, char *line, size_t dim)
962 if(!glh->enable || !glh->buffer || glh->max_lines == 0)
967 if(_glh_prepare_for_recall(glh, line))
972 node = _glh_find_id(glh, id);
976 if(!node || node->group != glh->group)
982 glh->recall = node;
994 * glh GlHistory * The input-line history maintenance object.
1009 int _glh_save_history(GlHistory *glh, const char *filename, const char *comment,
1013 _err_record_msg(glh->err, "Can't save history without filesystem access",
1025 if(!glh || !filename || !comment) {
1026 if(glh)
1027 _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG);
1036 return _glh_cant_save_history(glh, "Can't open", filename, NULL);
1043 for(head=glh->list.tail; head && --max_lines > 0; head=head->prev)
1047 head = glh->list.head;
1060 return _glh_cant_save_history(glh, "Error writing", filename, fp);
1068 return _glh_cant_save_history(glh, "Error writing", filename, fp);
1076 return _glh_cant_save_history(glh, "Error writing", filename, NULL);
1089 * glh GlHistory * The input-line history maintenance object.
1097 static int _glh_cant_save_history(GlHistory *glh, const char *message,
1100 _err_record_msg(glh->err, message, filename, " (",
1144 * glh GlHistory * The input-line history maintenance object.
1155 int _glh_load_history(GlHistory *glh, const char *filename, const char *comment,
1159 _err_record_msg(glh->err, "Can't load history without filesystem access",
1173 if(!glh || !filename || !comment || !line) {
1174 if(glh)
1175 _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG);
1186 _glh_clear_history(glh, 1);
1204 return _glh_cant_load_history(glh, filename, lineno,
1216 return _glh_cant_load_history(glh, filename, lineno,
1229 return _glh_cant_load_history(glh, filename, lineno,
1241 return _glh_cant_load_history(glh, filename, lineno,
1249 return _glh_cant_load_history(glh, filename, lineno, "Read error", fp);
1253 if(_glh_add_history(glh, line, 1)) {
1254 return _glh_cant_load_history(glh, filename, lineno,
1260 if(glh->list.tail) {
1261 glh->list.tail->timestamp = timestamp;
1262 glh->list.tail->group = group;
1277 static int _glh_cant_load_history(GlHistory *glh, const char *filename,
1288 _err_record_msg(glh->err, filename, ":", lnum, ":", message, END_ERR_MSG);
1377 * glh GlHistory * The input-line history maintenance object.
1389 int _glh_set_group(GlHistory *glh, unsigned group)
1394 if(!glh) {
1395 if(glh)
1396 _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG);
1403 if(group != glh->group) {
1407 if(_glh_cancel_search(glh))
1412 glh->group = group;
1421 * glh GlHistory * The input-line history maintenance object.
1425 int _glh_get_group(GlHistory *glh)
1427 return glh ? glh->group : 0;
1434 * glh GlHistory * The input-line history maintenance object.
1458 int _glh_show_history(GlHistory *glh, GlWriteFn *write_fn, void *data,
1473 if(!glh || !write_fn || !fmt) {
1474 if(glh)
1475 _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG);
1482 if(!glh->enable || !glh->list.head)
1489 snprintf(buffer, sizeof(buffer), "%lu", (unsigned long) glh->list.tail->id);
1495 for(node=glh->list.head; node; node=node->next) {
1508 oldest = glh->list.head;
1512 for(oldest=glh->list.tail; oldest; oldest=oldest->prev) {
1513 if((all_groups || oldest->group == glh->group) && --max_lines <= 0)
1521 oldest = glh->list.head;
1531 if(all_groups || node->group == glh->group) {
1620 * glh GlHistory * The input-line history maintenance object.
1629 int _glh_resize_history(GlHistory *glh, size_t bufsize)
1636 if(!glh) {
1648 if(glh->nbuff != nbuff) {
1652 (void) _glh_cancel_search(glh);
1656 if(glh->nbuff == 0 && nbuff>0) {
1657 glh->buffer = (GlhLineSeg *) malloc(sizeof(GlhLineSeg) * nbuff);
1658 if(!glh->buffer)
1660 glh->nbuff = nbuff;
1661 glh->nfree = glh->nbuff;
1662 glh->nbusy = 0;
1663 glh->nline = 0;
1667 glh->unused = glh->buffer;
1668 for(i=0; i<glh->nbuff-1; i++) {
1669 GlhLineSeg *seg = glh->unused + i;
1672 glh->unused[i].next = NULL;
1677 _glh_clear_history(glh, 1);
1678 free(glh->buffer);
1679 glh->buffer = NULL;
1680 glh->unused = NULL;
1681 glh->nbuff = 0;
1682 glh->nfree = 0;
1683 glh->nbusy = 0;
1684 glh->nline = 0;
1695 while(glh->list.head && glh->nbusy > nbuff)
1696 _glh_discard_line(glh, glh->list.head);
1710 GlhHashBucket *b = glh->hash.bucket + i;
1732 free(glh->buffer);
1736 glh->buffer = buffer;
1737 glh->nbuff = nbuff;
1738 glh->nbusy = nbusy;
1739 glh->nfree = nbuff - nbusy;
1740 glh->unused = glh->nfree > 0 ? (buffer + nbusy) : NULL;
1751 * glh GlHistory * The input-line history maintenance object.
1756 void _glh_limit_history(GlHistory *glh, int max_lines)
1758 if(!glh)
1763 if(max_lines >= 0 && max_lines != glh->max_lines) {
1771 for(node=glh->list.tail; node && ++nline <= max_lines; node=node->prev)
1782 while(glh->list.head && glh->list.head != oldest)
1783 _glh_discard_line(glh, glh->list.head);
1789 glh->max_lines = max_lines;
1798 * glh GlHistory * The input-line history maintenance object.
1803 void _glh_clear_history(GlHistory *glh, int all_groups)
1809 if(!glh)
1814 (void) _glh_cancel_search(glh);
1822 _rst_FreeList(glh->list.node_mem);
1823 glh->list.head = glh->list.tail = NULL;
1824 glh->nline = 0;
1825 glh->id_node = NULL;
1830 glh->hash.bucket[i].lines = NULL;
1831 _rst_FreeList(glh->hash.node_mem);
1835 if(glh->buffer) {
1836 glh->unused = glh->buffer;
1837 for(i=0; i<glh->nbuff-1; i++) {
1838 GlhLineSeg *seg = glh->unused + i;
1841 glh->unused[i].next = NULL;
1842 glh->nfree = glh->nbuff;
1843 glh->nbusy = 0;
1845 glh->unused = NULL;
1846 glh->nbusy = glh->nfree = 0;
1857 for(node=glh->list.head; node; node=next) {
1866 if(node->group == glh->group)
1867 _glh_discard_line(glh, node);
1877 * glh GlHistory * The input-line history maintenance object.
1881 void _glh_toggle_history(GlHistory *glh, int enable)
1883 if(glh)
1884 glh->enable = enable;
1891 * glh GlHistory * The history container object.
1896 static void _glh_discard_line(GlHistory *glh, GlhLineNode *node)
1904 glh->list.head = node->next;
1908 glh->list.tail = node->prev;
1913 if(node == glh->id_node)
1914 glh->id_node = NULL;
1919 if(node == glh->recall)
1920 _glh_cancel_search(glh);
1924 node->line = _glh_discard_copy(glh, node->line);
1928 (void) _del_FreeListNode(glh->list.node_mem, node);
1932 glh->nline--;
1940 * glh GlHistory * The input-line history maintenance object.
1955 int _glh_lookup_history(GlHistory *glh, GlhLineID id, const char **line,
1962 if(!glh)
1967 node = _glh_find_id(glh, id);
1981 if(node->line->len + 1 > glh->lbuf_dim) {
1983 char *lbuf = realloc(glh->lbuf, lbuf_dim);
1988 glh->lbuf_dim = lbuf_dim;
1989 glh->lbuf = lbuf;
1994 _glh_return_line(node->line, glh->lbuf, glh->lbuf_dim);
1998 *line = glh->lbuf;
2017 * glh GlHistory * The input-line history maintenance object.
2022 static GlhLineNode *_glh_find_id(GlHistory *glh, GlhLineID id)
2028 if(!glh->enable || !glh->list.head)
2034 node = glh->id_node;
2036 node = glh->list.head;
2043 glh->id_node = node ? node : glh->list.tail;
2050 glh->id_node = node ? node : glh->list.head;
2063 * glh GlHistory * The input-line history maintenance object.
2073 void _glh_state_of_history(GlHistory *glh, int *enabled, unsigned *group,
2076 if(glh) {
2078 *enabled = glh->enable;
2080 *group = glh->group;
2082 *max_lines = glh->max_lines;
2090 * glh GlHistory * The input-line history maintenance object.
2103 void _glh_range_of_history(GlHistory *glh, unsigned long *oldest,
2106 if(glh) {
2108 *oldest = glh->list.head ? glh->list.head->id : 0;
2110 *newest = glh->list.tail ? glh->list.tail->id : 0;
2112 *nlines = glh->nline;
2121 * glh GlHistory * The input-line history maintenance object.
2127 void _glh_size_of_history(GlHistory *glh, size_t *buff_size, size_t *buff_used)
2129 if(glh) {
2131 *buff_size = (glh->nbusy + glh->nfree) * GLH_SEG_SIZE;
2136 *buff_used = glh->nbusy * GLH_SEG_SIZE;
2146 * glh GlHistory * The container of the history list.
2151 const char *_glh_last_error(GlHistory *glh)
2153 return glh ? _err_get_msg(glh->err) : "NULL GlHistory argument";
2161 * glh GlHistory * The history maintenance buffer.
2169 static GlhHashNode *_glh_acquire_copy(GlHistory *glh, const char *line,
2178 bucket = glh_find_bucket(glh, line, n);
2199 while(glh->nfree < nseg && glh->nbusy > 0)
2200 _glh_discard_line(glh, glh->list.head);
2205 if(glh->nfree < nseg)
2211 for(i=0,seg=glh->unused; i<nseg-1; i++,seg=seg->next, offset+=GLH_SEG_SIZE)
2218 hnode = (GlhHashNode *) _new_FreeListNode(glh->hash.node_mem);
2225 hnode->head = glh->unused;
2226 glh->unused = seg->next;
2228 glh->nbusy += nseg;
2229 glh->nfree -= nseg;
2256 * glh GlHistory * The history container object.
2261 static GlhHashNode *_glh_discard_copy(GlHistory *glh, GlhHashNode *hnode)
2302 tail->next = glh->unused;
2303 glh->unused = hnode->head;
2304 glh->nbusy -= nseg;
2305 glh->nfree += nseg;
2310 hnode = (GlhHashNode *) _del_FreeListNode(glh->hash.node_mem, hnode);
2324 * glh GlHistory * The history container object.
2331 static GlhHashBucket *glh_find_bucket(GlHistory *glh, const char *line,
2340 return glh->hash.bucket + (h % GLH_HASH_SIZE);
2491 * glh GlHistory * The input-line history maintenance object.
2497 static int _glh_prepare_for_recall(GlHistory *glh, char *line)
2506 if(glh->recall && glh->recall == glh->list.tail &&
2507 !_glh_is_line(glh->recall->line, line, strlen(line))) {
2508 _glh_cancel_search(glh);
2515 if(!glh->recall) {
2516 if(_glh_add_history(glh, line, 1))
2518 glh->recall = glh->list.tail;
2524 glh->seq--;
2533 * glh GlHistory * The input-line history maintenance object.
2538 int _glh_search_active(GlHistory *glh)
2540 return glh && glh->recall;