/* Move h to the next string that's a tab completion of the string s, * looking at only the first len characters of s, and return that * string. If there isn't one, or if len is 0, don't move h and return * s. */ char *get_history_completion(linestruct **h, const char *s, size_t len) { assert(s != NULL); if (len > 0) { linestruct *hage = NULL, *hbot = NULL, *p; assert(h != NULL); if (*h == search_history) { hage = searchage; hbot = searchbot; } else if (*h == replace_history) { hage = replaceage; hbot = replacebot; } assert(hage != NULL && hbot != NULL); /* Search the history list from the current position to the * bottom for a match of len characters. Skip over an exact * match. */ p = find_history((*h)->next, hbot, s, len); while (p != NULL && strcmp(p->data, s) == 0) p = find_history(p->next, hbot, s, len); if (p != NULL) { *h = p; return (*h)->data; } /* Search the history list from the top to the current position * for a match of len characters. Skip over an exact match. */ p = find_history(hage, *h, s, len); while (p != NULL && strcmp(p->data, s) == 0) p = find_history(p->next, *h, s, len); if (p != NULL) { *h = p; return (*h)->data; } } /* If we're here, we didn't find a match, we didn't find an inexact * match, or len is 0. Return s. */ return (char *)s; }
/* SHOW_HISTORY -- Print the contents of the history buffer on the output * stream, preceeding each command block with a 3 digit command number. * Show at most min (max_commands, MAX_SHOWHIST) command blocks. */ void show_history ( FILE *fp, int max_commands ) { char *recptr[MAX_SHOWHIST]; char cmdblk[SZ_CMDBLK+1]; int record; char *find_history(); /* Flush the "history" command so that it shows up in the history. */ yy_startblock (LOG); /* Determine the number of records to show. */ for (record=0; record < MAX_SHOWHIST; record++) if ((recptr[record] = find_history (record+1)) == NULL) break; if (max_commands > 0) record = (record < max_commands) ? record : max_commands; /* Print the records with the 3 digit record number plus a blank * on the first line and 4 blanks at the beginning of each successive * line of the block. */ while (record > 0) { fprintf (fp, "%3d ", (histnum - (--record)) % 1000); fetch_history (recptr[record], cmdblk, SZ_CMDBLK+1); print_command (fp, cmdblk, "", " "); fflush (fp); } }
/* Update a history list. h should be the current position in the * list. */ void update_history(linestruct **h, const char *s) { linestruct **hage = NULL, **hbot = NULL, *p; assert(h != NULL && s != NULL); if (*h == search_history) { hage = &searchage; hbot = &searchbot; } else if (*h == replace_history) { hage = &replaceage; hbot = &replacebot; } assert(hage != NULL && hbot != NULL); /* If this string is already in the history, delete it. */ p = find_history(*hage, *hbot, s, strlen(s)); if (p != NULL) { linestruct *foo, *bar; /* If the string is at the beginning, move the beginning down to * the next string. */ if (p == *hage) *hage = (*hage)->next; /* Delete the string. */ foo = p; bar = p->next; unlink_node(foo); delete_node(foo); renumber(bar); } /* If the history is full, delete the beginning entry to make room * for the new entry at the end. We assume that MAX_SEARCH_HISTORY * is greater than zero. */ if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) { linestruct *foo = *hage; *hage = (*hage)->next; unlink_node(foo); delete_node(foo); renumber(*hage); } /* Add the new entry to the end. */ (*hbot)->data = mallocstrcpy((*hbot)->data, s); splice_node(*hbot, make_new_node(*hbot), (*hbot)->next); *hbot = (*hbot)->next; (*hbot)->data = mallocstrcpy(NULL, ""); /* Indicate that the history's been changed. */ history_changed = TRUE; /* Set the current position in the list to the bottom. */ *h = *hbot; }
/* Move h to the next string that's a tab completion of the string s, * looking at only the first len characters of s, and return that * string. If there isn't one, or if len is 0, don't move h and return * s. */ char *get_history_completion(linestruct **h, char *s, size_t len) { if (len > 0) { linestruct *htop = NULL, *hbot = NULL, *p; if (*h == search_history) { htop = searchtop; hbot = searchbot; } else if (*h == replace_history) { htop = replacetop; hbot = replacebot; } else if (*h == execute_history) { htop = executetop; hbot = executebot; } /* Search the history list from the current position to the top * for a match of len characters. Skip over an exact match. */ p = find_history((*h)->prev, htop, s, len); while (p != NULL && strcmp(p->data, s) == 0) p = find_history(p->prev, htop, s, len); if (p != NULL) { *h = p; return mallocstrcpy(s, (*h)->data); } /* Search the history list from the bottom to the current position * for a match of len characters. Skip over an exact match. */ p = find_history(hbot, *h, s, len); while (p != NULL && strcmp(p->data, s) == 0) p = find_history(p->prev, *h, s, len); if (p != NULL) { *h = p; return mallocstrcpy(s, (*h)->data); } } /* If we're here, we didn't find a match, we didn't find an inexact * match, or len is 0. Return s. */ return (char *)s; }
/* Update a history list (the one in which item is the current position) * with a fresh string text. That is: add text, or move it to the end. */ void update_history(linestruct **item, const char *text) { linestruct **htop = NULL, **hbot = NULL, *thesame; if (*item == search_history) { htop = &searchtop; hbot = &searchbot; } else if (*item == replace_history) { htop = &replacetop; hbot = &replacebot; } else if (*item == execute_history) { htop = &executetop; hbot = &executebot; } /* See if the string is already in the history. */ thesame = find_history(*hbot, *htop, text, HIGHEST_POSITIVE); /* If an identical string was found, delete that item. */ if (thesame != NULL) { linestruct *after = thesame->next; /* If the string is at the head of the list, move the head. */ if (thesame == *htop) *htop = after; unlink_node(thesame); renumber_from(after); } /* If the history is full, delete the oldest item (the one at the * head of the list), to make room for a new item at the end. */ if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) { linestruct *oldest = *htop; *htop = (*htop)->next; unlink_node(oldest); renumber_from(*htop); } /* Store the fresh string in the last item, then create a new item. */ (*hbot)->data = mallocstrcpy((*hbot)->data, text); splice_node(*hbot, make_new_node(*hbot)); *hbot = (*hbot)->next; (*hbot)->data = mallocstrcpy(NULL, ""); /* Indicate that the history needs to be saved on exit. */ history_changed = TRUE; /* Set the current position in the list to the bottom. */ *item = *hbot; }
/* GET_HISTORY -- Fetch the indicated command from the history buffer, * returning OK if found, ERR otherwise. */ int get_history (int record, char *command, int maxch) { char *recptr; char *find_history(); if ((recptr = find_history (record)) == NULL) { *command = EOS; return (ERR); } else { fetch_history (recptr, command, maxch); return (OK); } }