1 /*
2 DF-SHOW: An interactive directory/file browser written for Unix-like systems.
3 Based on the applications from the PC-DOS DF-EDIT suite by Larry Kroeker.
4 Copyright (C) 2018-2021 Robert Ian Hawdon
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #define _GNU_SOURCE
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <ncurses.h>
24 #include <string.h>
25 #include <wchar.h>
26 #include "colors.h"
27 #include "menu.h"
28
cmp_menu_ref(const void * lhs,const void * rhs)29 int cmp_menu_ref(const void *lhs, const void *rhs)
30 {
31
32 menuDef *dforderA = (menuDef *)lhs;
33 menuDef *dforderB = (menuDef *)rhs;
34
35 return strcoll(dforderA->refLabel, dforderB->refLabel);
36
37 }
38
updateMenuItem(menuDef ** dfMenu,int * menuSize,char * refLabel,wchar_t * displayLabel)39 void updateMenuItem(menuDef **dfMenu, int *menuSize, char* refLabel, wchar_t* displayLabel){
40 // To Do
41 int i;
42 for(i = 0; i < *menuSize; i++){
43 if (!strcmp(((*dfMenu)[i].refLabel), refLabel)){
44 swprintf((*dfMenu)[i].displayLabel, 32, L"%ls", displayLabel);
45 break;
46 }
47 }
48 return;
49 }
50
addMenuItem(menuDef ** dfMenu,int * pos,char * refLabel,wchar_t * displayLabel,int hotKey)51 void addMenuItem(menuDef **dfMenu, int *pos, char* refLabel, wchar_t* displayLabel, int hotKey){
52
53 int menuPos = *pos;
54 int charCount = 0;
55 int i;
56 menuDef *tmp;
57
58 if (menuPos == 0){
59 tmp = malloc(sizeof(menuDef) * 2);
60 } else {
61 tmp = realloc(*dfMenu, (menuPos + 1) * (sizeof(menuDef) + 1) );
62 }
63 if (tmp){
64 *dfMenu = tmp;
65 }
66
67 sprintf((*dfMenu)[menuPos].refLabel, "%s", refLabel);
68 swprintf((*dfMenu)[menuPos].displayLabel, 32, L"%ls", displayLabel);
69 (*dfMenu)[menuPos].hotKey = hotKey;
70
71 for (i = 0; i < wcslen(displayLabel); i++)
72 {
73 if ( displayLabel[i] == '!' || displayLabel[i] == '<' || displayLabel[i] == '>' || displayLabel[i] == '\\') {
74 i++;
75 charCount++;
76 } else {
77 charCount++;
78 }
79 }
80 (*dfMenu)[menuPos].displayLabelSize = charCount;
81
82 qsort((*dfMenu), menuPos + 1, sizeof(menuDef), cmp_menu_ref);
83
84 ++*pos;
85
86 }
87
genMenuDisplayLabel(wchar_t * preMenu,menuDef * dfMenu,int size,wchar_t * postMenu,int comma)88 wchar_t * genMenuDisplayLabel(wchar_t* preMenu, menuDef* dfMenu, int size, wchar_t* postMenu, int comma){
89 wchar_t * output;
90 int gapSize;
91 int currentLen = 0;
92 int i;
93
94 output = malloc(sizeof(wchar_t) * ( wcslen(preMenu) + 2));
95 if (wcscmp(preMenu, L"")){
96 wcscpy(output, preMenu);
97 wcscat(output, L" ");
98 } else {
99 wcscpy(output, L"\0");
100 }
101 for (i = 0; i < size ; i++){
102 output = realloc(output, ((i + 1) * sizeof(dfMenu[i].displayLabel) + wcslen(output) + 1) * sizeof(wchar_t) );
103 if ( i == 0 ){
104 currentLen = currentLen + dfMenu[i].displayLabelSize;
105 if ( currentLen - 1 < COLS){
106 wcscat(output, dfMenu[i].displayLabel);
107 } else if ( currentLen +1 > COLS && i == 0){
108 wcscat(output, L"");
109 }
110 } else {
111 if (comma == 1){
112 gapSize = 2;
113 } else if (comma == -1) {
114 gapSize = 0;
115 } else {
116 gapSize = 1;
117 }
118 currentLen = currentLen + dfMenu[i].displayLabelSize + gapSize;
119 if (currentLen - 1 < COLS){
120 if (comma == 1){
121 wcscat(output, L", ");
122 } else if (comma == 0) {
123 wcscat(output, L" ");
124 }
125 wcscat(output, dfMenu[i].displayLabel);
126 }
127 }
128 }
129 output = realloc(output, (sizeof(wchar_t) * (wcslen(output) + wcslen(postMenu) + 2) ));
130 if (wcscmp(postMenu, L"")){
131 wcscat(output, L" ");
132 wcscat(output, postMenu);
133 } else {
134 wcscat(output, L"\0");
135 }
136 return output;
137 }
138
menuHotkeyLookup(menuDef * dfMenu,char * refLabel,int size)139 int menuHotkeyLookup(menuDef* dfMenu, char* refLabel, int size){
140 int i;
141 int r = -1;
142 for (i = 0; i < size; i++){
143 if (!strcmp(dfMenu[i].refLabel, refLabel)){
144 r = dfMenu[i].hotKey;
145 }
146 }
147 return r;
148 }
149
altHotkey(int key)150 int altHotkey(int key)
151 {
152 int alt;
153 if ((key < 123) && (key > 96)){
154 alt = key - 32;
155 } else if ((key < 91) && (key > 64)){
156 alt = key + 32;
157 } else {
158 alt = -1;
159 }
160 return(alt);
161 }
162
wPrintMenu(int line,int col,wchar_t * menustring)163 void wPrintMenu(int line, int col, wchar_t *menustring)
164 {
165 int i, len, charcount, pad;
166 charcount = 0;
167 move(line, col);
168 clrtoeol();
169 len = wcslen(menustring);
170 setColors(COMMAND_PAIR);
171 for (i = 0; i < len; i++)
172 {
173 if ( menustring[i] == '!' ) {
174 setColors(HILITE_PAIR);
175 i++;
176 mvprintw(line, col + charcount, "%lc", menustring[i]);
177 setColors(COMMAND_PAIR);
178 charcount++;
179 } else if ( menustring[i] == '<' ) {
180 setColors(HILITE_PAIR);
181 i++;
182 mvprintw(line, col + charcount, "%lc", menustring[i]);
183 charcount++;
184 } else if ( menustring[i] == '>' ) {
185 setColors(COMMAND_PAIR);
186 if (i < (len - 1)){
187 i++;
188 mvprintw(line, col + charcount, "%lc", menustring[i]);
189 charcount++;
190 }
191 } else if ( menustring[i] == '\\' ) {
192 i++;
193 mvprintw(line, col + charcount, "%lc", menustring[i]);
194 charcount++;
195 } else {
196 mvprintw(line, col + charcount, "%lc", menustring[i]);
197 charcount++;
198 }
199 }
200 pad = COLS - charcount;
201 for (i = 0; i < pad; i++)
202 {
203 mvprintw(line, col + charcount, " ");
204 charcount++;
205 }
206 }
207
printMenu(int line,int col,char * menustring)208 void printMenu(int line, int col, char *menustring)
209 {
210 // Small wrapper to seemlessly forward calls to the wide char version
211 wchar_t *wMenuString;
212 wMenuString = malloc(sizeof(wchar_t) * (strlen(menustring) + 1));
213 swprintf(wMenuString, strlen(menustring) + 1, L"%s", menustring);
214 wPrintMenu(line, col, wMenuString);
215 free(wMenuString);
216 }
217