| #include <stdlib.h> /* for malloc */ |
| #include <stdio.h> |
| #include <strings.h> |
| #include <wchar.h> |
| #include "wc_history.h" |
| |
| #define WIN32_LEAN_AND_MEAN 1 |
| #include <windows.h> |
| #include <R_ext/Error.h> |
| |
| static int HIST_SIZE = 512; |
| static int hist_pos = 0, hist_last = 0, gl_beep_on = 1; |
| static wchar_t **hist_buf; |
| static int wgl_init_done = -1; |
| |
| static void gl_error(char *msg) |
| { |
| char buf[1001]; |
| |
| wgl_init_done = 1; |
| snprintf(buf, 1000, |
| "%s\nDisabling commands history for this session", msg); |
| buf[1000] = '\0'; |
| R_ShowMessage(buf); |
| } |
| |
| static void gl_beep(void) |
| { |
| if(gl_beep_on) MessageBeep(MB_OK); |
| } |
| |
| static wchar_t *hist_save(const wchar_t *p) |
| /* makes a copy of the string */ |
| { |
| wchar_t *s = 0; |
| int len = wcslen(p); |
| wchar_t *nl = wcschr(p, L'\n'); |
| |
| if (nl) { |
| if ((s = (wchar_t *) malloc(len * sizeof(wchar_t)))) { |
| wcsncpy(s, p, len-1); |
| s[len-1] = 0; |
| } |
| } else { |
| if ((s = (wchar_t *) malloc((len+1) * sizeof(wchar_t)))) |
| wcscpy(s, p); |
| } |
| if (s == 0) |
| gl_error("*** Error: hist_save() failed on malloc"); |
| |
| return s; |
| } |
| |
| void wgl_hist_init(int size, int beep) |
| { |
| int i; |
| |
| HIST_SIZE = size; |
| hist_buf = (wchar_t **) malloc(size * sizeof(wchar_t *)); |
| if(!hist_buf) { |
| gl_error("\n*** Error: wgl_hist_init() failed on malloc\n"); |
| return; |
| } |
| hist_buf[0] = L""; |
| for (i = 1; i < HIST_SIZE; i++) |
| hist_buf[i] = (wchar_t *)0; |
| hist_pos = hist_last = 0; |
| wgl_init_done = 0; |
| gl_beep_on = beep; |
| } |
| |
| void wgl_histadd(const wchar_t *buf) |
| { |
| const wchar_t *p = buf; |
| |
| if(wgl_init_done > 0) return; |
| while (*p == ' ' || *p == '\t' || *p == '\n') p++; |
| if (*p) { |
| hist_buf[hist_last] = hist_save(buf); |
| hist_last = hist_last + 1; |
| if(hist_last > HIST_SIZE - 1) { |
| int i, size = HIST_SIZE + 512; |
| hist_buf = (wchar_t **) |
| realloc(hist_buf, size * sizeof(wchar_t *)); |
| if(!hist_buf) { |
| gl_error("*** Error: wgl_histadd() failed on realloc"); |
| return; |
| } |
| for(i = HIST_SIZE; i < size; i++) |
| hist_buf[i] = (wchar_t *)0; |
| HIST_SIZE = size; |
| } |
| hist_buf[hist_last] = L""; |
| } |
| hist_pos = hist_last; |
| } |
| |
| wchar_t *wgl_hist_prev(void) |
| /* loads previous hist entry into input buffer, sticks on first */ |
| { |
| wchar_t *p = 0; |
| int next = hist_pos - 1; |
| |
| if(wgl_init_done) return L""; |
| if (hist_buf[hist_pos] != 0 && next >= 0) { |
| hist_pos = next; |
| p = hist_buf[hist_pos]; |
| } |
| if (p == 0) { |
| p = L""; |
| gl_beep(); |
| } |
| return p; |
| } |
| |
| wchar_t *wgl_hist_next(void) |
| /* loads next hist entry into input buffer, clears on last */ |
| { |
| wchar_t *p = 0; |
| |
| if(wgl_init_done) return L""; |
| if (hist_pos != hist_last) { |
| hist_pos = hist_pos+1; |
| p = hist_buf[hist_pos]; |
| } |
| if (p == 0) { |
| p = L""; |
| gl_beep(); |
| } |
| return p; |
| } |
| |
| void wgl_savehistory(const char *file, int size) |
| { |
| FILE *fp; |
| int i, init; |
| |
| if (wgl_init_done || !file || !hist_last) return; |
| fp = fopen(file, "w"); |
| if (!fp) { |
| char msg[256]; |
| snprintf(msg, 256, "Unable to open %s", file); |
| R_ShowMessage(msg); |
| return; |
| } |
| init = hist_last - size; |
| init = (init < 0) ? 0 : init; |
| for (i = init; i < hist_last; i++) |
| fprintf(fp, "%ls\n", hist_buf[i]); |
| fclose(fp); |
| } |
| |
| void wgl_loadhistory(const char *file) |
| { |
| FILE *fp; |
| int i; |
| wchar_t buf[1000]; |
| |
| if (wgl_init_done || !file) return; |
| fp = fopen(file, "r"); |
| if (!fp) return; |
| for(i = 0;; i++) { |
| if(!fgetws(buf, 1000, fp)) break; |
| wgl_histadd(buf); |
| } |
| fclose(fp); |
| } |
| |
| void wgl_savehistoryW(const wchar_t *file, int size) |
| { |
| FILE *fp; |
| int i, init; |
| |
| if (wgl_init_done || !file || !hist_last) return; |
| fp = _wfopen(file, L"w"); |
| if (!fp) { |
| char msg[256]; |
| snprintf(msg, 256, "Unable to open %ls", file); |
| R_ShowMessage(msg); |
| return; |
| } |
| init = hist_last - size; |
| init = (init < 0) ? 0 : init; |
| for (i = init; i < hist_last; i++) |
| fprintf(fp, "%ls\n", hist_buf[i]); |
| fclose(fp); |
| } |
| |
| void wgl_loadhistoryW(const wchar_t *file) |
| { |
| FILE *fp; |
| int i; |
| wchar_t buf[1000]; |
| |
| if (wgl_init_done || !file) return; |
| fp = _wfopen(file, L"r"); |
| if (!fp) return; |
| for(i = 0;; i++) { |
| if(!fgetws(buf, 1000, fp)) break; |
| wgl_histadd(buf); |
| } |
| fclose(fp); |
| } |