dmenu

Kris's build of dmenu
git clone git clone https://git.krisyotam.com/krisyotam/dmenu.git
Log | Files | Refs | README | LICENSE

navhistory.c (3718B)


      1 static char *histfile;
      2 static char **history;
      3 static size_t histsz, histpos;
      4 static size_t cap = 0;
      5 static struct item *backup_items = NULL;
      6 
      7 void
      8 cleanhistory(void)
      9 {
     10 	int i;
     11 
     12 	for (i = 0; i < histsz; i++) {
     13 		free(history[i]);
     14 	}
     15 	free(history);
     16 }
     17 
     18 void
     19 loadhistory(void)
     20 {
     21 	FILE *fp = NULL;
     22 	size_t llen;
     23 	char *line;
     24 
     25 	if (!histfile) {
     26 		return;
     27 	}
     28 
     29 	fp = fopen(histfile, "r");
     30 	if (!fp) {
     31 		return;
     32 	}
     33 
     34 	for (;;) {
     35 		line = NULL;
     36 		llen = 0;
     37 		if (-1 == getline(&line, &llen, fp)) {
     38 			if (ferror(fp)) {
     39 				die("failed to read history");
     40 			}
     41 			free(line);
     42 			break;
     43 		}
     44 
     45 		addhistory(line);
     46 		free(line);
     47 	}
     48 	histpos = histsz;
     49 
     50 	if (fclose(fp)) {
     51 		die("failed to close file %s", histfile);
     52 	}
     53 }
     54 
     55 void
     56 navhistory(int dir)
     57 {
     58 	static char def[BUFSIZ];
     59 	char *p = NULL;
     60 	size_t len = 0;
     61 
     62 	if (!history || histpos + 1 == 0)
     63 		return;
     64 
     65 	if (histsz == histpos) {
     66 		strncpy(def, text, sizeof(def));
     67 	}
     68 
     69 	switch(dir) {
     70 	case 1:
     71 		if (histpos < histsz - 1) {
     72 			p = history[++histpos];
     73 		} else if (histpos == histsz - 1) {
     74 			p = def;
     75 			histpos++;
     76 		}
     77 		break;
     78 	case -1:
     79 		if (histpos > 0) {
     80 			p = history[--histpos];
     81 		}
     82 		break;
     83 	}
     84 	if (p == NULL) {
     85 		return;
     86 	}
     87 
     88 	len = MIN(strlen(p), BUFSIZ - 1);
     89 	strncpy(text, p, len);
     90 	text[len] = '\0';
     91 	cursor = len;
     92 	match();
     93 }
     94 
     95 void
     96 addhistory(char *input)
     97 {
     98 	unsigned int i;
     99 
    100 	if (!histfile ||
    101 	    0 == maxhist ||
    102 	    0 == strlen(input)) {
    103 		return;
    104 	}
    105 
    106 	strtok(input, "\n");
    107 
    108 	if (histnodup) {
    109 		for (i = 0; i < histsz; i++) {
    110 			if (!strcmp(input, history[i])) {
    111 				return;
    112 			}
    113 		}
    114 	}
    115 
    116 	if (cap == histsz) {
    117 		reallochistory();
    118 	}
    119 
    120 	history[histsz] = strdup(input);
    121 	histsz++;
    122 }
    123 
    124 void
    125 addhistoryitem(struct item *item)
    126 {
    127 	#if SEPARATOR_PATCH
    128 	if (separator && item->text_output && item->text != item->text_output) {
    129 		int histlen = strlen(item->text) + strlen(item->text_output) + 2;
    130 		char *histitem = ecalloc(histlen + 1, sizeof(char *));
    131 		snprintf(histitem, histlen, "%s%c%s", item->text, separator, item->text_output);
    132 		addhistory(histitem);
    133 		free(histitem);
    134 		return;
    135 	}
    136 	#endif // SEPARATOR_PATCH
    137 
    138 	addhistory(item->text);
    139 }
    140 
    141 void
    142 reallochistory(void)
    143 {
    144 	size_t oldcap = cap;
    145 	cap += 64;
    146 	char **newhistory = realloc(history, cap * sizeof *history);
    147 	if (!newhistory) {
    148 		die("failed to realloc memory");
    149 	}
    150 
    151 	history = newhistory;
    152 	memset(history + oldcap, 0, (cap - oldcap) * sizeof *history);
    153 }
    154 
    155 void
    156 togglehistoryitems(void)
    157 {
    158 	int i;
    159 	#if SEPARATOR_PATCH || TSV_PATCH
    160 	char *p;
    161 	#endif // SEPARATOR_PATCH
    162 
    163 	if (!histfile)
    164 		return;
    165 
    166 	if (backup_items) {
    167 		restorebackupitems();
    168 		return;
    169 	}
    170 
    171 	backup_items = items;
    172 	items = calloc(histsz + 1, sizeof(struct item));
    173 	if (!items) {
    174 		die("cannot allocate memory");
    175 	}
    176 
    177 	for (i = 0; i < histsz; i++) {
    178 		items[i].text = strdup(history[i]);
    179 		#if SEPARATOR_PATCH
    180 		if (separator && (p = sepchr(items[i].text, separator)) != NULL) {
    181 			*p = '\0';
    182 			items[i].text_output = ++p;
    183 		} else {
    184 			items[i].text_output = items[i].text;
    185 		}
    186 		#elif TSV_PATCH
    187 		items[i].stext = strdup(items[i].text);
    188 		if ((p = strchr(items[i].stext, '\t')))
    189 			*p = '\0';
    190 		#endif // SEPARATOR_PATCH
    191 	}
    192 }
    193 
    194 void
    195 restorebackupitems(void)
    196 {
    197 	size_t i;
    198 
    199 	if (!backup_items)
    200 		return;
    201 
    202 	for (i = 0; items && items[i].text; ++i) {
    203 		free(items[i].text);
    204 	}
    205 	free(items);
    206 
    207 	items = backup_items;
    208 	backup_items = NULL;
    209 }
    210 
    211 void
    212 savehistory(void)
    213 {
    214 	unsigned int i;
    215 	FILE *fp;
    216 
    217 	if (!histfile || 0 == maxhist)
    218 		return;
    219 
    220 	fp = fopen(histfile, "w");
    221 	if (!fp) {
    222 		die("failed to open %s", histfile);
    223 	}
    224 
    225 	for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) {
    226 		if (0 >= fprintf(fp, "%s\n", history[i])) {
    227 			die("failed to write to %s", histfile);
    228 		}
    229 	}
    230 
    231 	if (fclose(fp)) {
    232 		die("failed to close file %s", histfile);
    233 	}
    234 }