1 /* $Id: cdkscroll.c,v 1.13 2016/12/04 15:22:16 tom Exp $ */
2 
3 #include <cdk_test.h>
4 
5 #ifdef XCURSES
6 char *XCursesProgramName = "cdkscroll";
7 #endif
8 
9 /*
10  * Declare file local prototypes.
11  */
12 static int widgetCB (EObjectType cdktype, void *object, void *clientData, chtype key);
13 
14 /*
15  * Define file local variables.
16  */
17 static const char *FPUsage = "-l List | -f filename [-s Scroll Bar Position] [-n Numbers] [-i Item Index] [-T Title] [-B Buttons] [-O Output File] [-X X Position] [-Y Y Position] [-H Height] [-W Width] [-N] [-S]";
18 
19 /*
20  *
21  */
main(int argc,char ** argv)22 int main (int argc, char **argv)
23 {
24    /* *INDENT-EQLS* */
25    CDKSCREEN *cdkScreen         = 0;
26    CDKSCROLL *widget            = 0;
27    CDKBUTTONBOX *buttonWidget   = 0;
28    char *CDK_WIDGET_COLOR       = 0;
29    char *temp                   = 0;
30    chtype *holder               = 0;
31    int answer                   = 0;
32    int spos                     = NONE;
33    int buttonCount              = 0;
34    int selection                = 0;
35    int scrollLines              = -1;
36    int shadowHeight             = 0;
37    FILE *fp                     = stderr;
38    char **scrollList            = 0;
39    char **buttonList            = 0;
40    int j1, j2;
41 
42    CDK_PARAMS params;
43    boolean boxWidget;
44    boolean shadowWidget;
45    char *buttons;
46    char *filename;
47    char *list;
48    char *outputFile;
49    char *title;
50    int height;
51    int numberOutput;
52    int numbers;
53    int width;
54    int xpos;
55    int ypos;
56 
57    CDKparseParams (argc, argv, &params, "f:il:ns:B:O:T:" CDK_CLI_PARAMS);
58 
59    /* *INDENT-EQLS* */
60    xpos            = CDKparamValue (&params, 'X', CENTER);
61    ypos            = CDKparamValue (&params, 'Y', CENTER);
62    height          = CDKparamValue (&params, 'H', 1);
63    width           = CDKparamValue (&params, 'W', 1);
64    boxWidget       = CDKparamValue (&params, 'N', TRUE);
65    shadowWidget    = CDKparamValue (&params, 'S', FALSE);
66    numberOutput    = CDKparamValue (&params, 'i', FALSE);
67    numbers         = CDKparamValue (&params, 'n', FALSE);
68    filename        = CDKparamString (&params, 'f');
69    list            = CDKparamString (&params, 'l');
70    buttons         = CDKparamString (&params, 'B');
71    outputFile      = CDKparamString (&params, 'O');
72    title           = CDKparamString (&params, 'T');
73 
74    spos = CDKparsePosition (CDKparamString (&params, 's'));
75 
76    /* If the user asked for an output file, try to open it. */
77    if (outputFile != 0)
78    {
79       if ((fp = fopen (outputFile, "w")) == 0)
80       {
81 	 fprintf (stderr, "%s: Can not open output file %s\n", argv[0], outputFile);
82 	 ExitProgram (CLI_ERROR);
83       }
84    }
85 
86    /* Did they provide a list of items. */
87    if (list == 0)
88    {
89       /* Maybe they gave a filename to use to read. */
90       if (filename != 0)
91       {
92 	 /* Read the file in. */
93 	 scrollLines = CDKreadFile (filename, &scrollList);
94 
95 	 /* Check if there was an error. */
96 	 if (scrollLines == -1)
97 	 {
98 	    fprintf (stderr, "Error: Could not open the file '%s'.\n", filename);
99 	    ExitProgram (CLI_ERROR);
100 	 }
101       }
102       else
103       {
104 	 /* They didn't provide anything. */
105 	 fprintf (stderr, "Usage: %s %s\n", argv[0], FPUsage);
106 	 ExitProgram (CLI_ERROR);
107       }
108    }
109    else
110    {
111       /* Split the scroll lines up. */
112       scrollList = CDKsplitString (list, '\n');
113       scrollLines = (int)CDKcountStrings ((CDK_CSTRING2) scrollList);
114    }
115 
116    cdkScreen = initCDKScreen (NULL);
117 
118    /* Start color. */
119    initCDKColor ();
120 
121    /* Check if the user wants to set the background of the main screen. */
122    if ((temp = getenv ("CDK_SCREEN_COLOR")) != 0)
123    {
124       holder = char2Chtype (temp, &j1, &j2);
125       wbkgd (cdkScreen->window, holder[0]);
126       wrefresh (cdkScreen->window);
127       freeChtype (holder);
128    }
129 
130    /* Get the widget color background color. */
131    if ((CDK_WIDGET_COLOR = getenv ("CDK_WIDGET_COLOR")) == 0)
132    {
133       CDK_WIDGET_COLOR = 0;
134    }
135 
136    /* Create the scrolling list. */
137    widget = newCDKScroll (cdkScreen, xpos, ypos, spos,
138 			  height, width, title,
139 			  (CDK_CSTRING2) scrollList, scrollLines,
140 			  numbers, A_REVERSE,
141 			  boxWidget, shadowWidget);
142 
143    /* Make sure we could create the widget. */
144    if (widget == 0)
145    {
146       CDKfreeStrings (scrollList);
147 
148       destroyCDKScreen (cdkScreen);
149       endCDK ();
150 
151       fprintf (stderr,
152 	       "Error: Could not create the scrolling list. "
153 	       "Is the window too small?\n");
154 
155       ExitProgram (CLI_ERROR);
156    }
157 
158    /* Split the buttons if they supplied some. */
159    if (buttons != 0)
160    {
161       /* Split the button list up. */
162       buttonList = CDKsplitString (buttons, '\n');
163       buttonCount = (int)CDKcountStrings ((CDK_CSTRING2) buttonList);
164 
165       /* We need to create a buttonbox widget. */
166       buttonWidget = newCDKButtonbox (cdkScreen,
167 				      getbegx (widget->win),
168 				      (getbegy (widget->win)
169 				       + widget->boxHeight - 1),
170 				      1, widget->boxWidth - 1,
171 				      0, 1, buttonCount,
172 				      (CDK_CSTRING2) buttonList, buttonCount,
173 				      A_REVERSE, boxWidget, FALSE);
174       CDKfreeStrings (buttonList);
175 
176       setCDKButtonboxULChar (buttonWidget, ACS_LTEE);
177       setCDKButtonboxURChar (buttonWidget, ACS_RTEE);
178 
179       /*
180        * We need to set the lower left and right
181        * characters of the widget.
182        */
183       setCDKScrollLLChar (widget, ACS_LTEE);
184       setCDKScrollLRChar (widget, ACS_RTEE);
185 
186       /*
187        * Bind the Tab key in the widget to send a
188        * Tab key to the button box widget.
189        */
190       bindCDKObject (vSCROLL, widget, KEY_TAB, widgetCB, buttonWidget);
191       bindCDKObject (vSCROLL, widget, CDK_NEXT, widgetCB, buttonWidget);
192       bindCDKObject (vSCROLL, widget, CDK_PREV, widgetCB, buttonWidget);
193 
194       /* Check if the user wants to set the background of the widget. */
195       setCDKButtonboxBackgroundColor (buttonWidget, CDK_WIDGET_COLOR);
196 
197       /* Draw the button widget. */
198       drawCDKButtonbox (buttonWidget, boxWidget);
199    }
200 
201    /*
202     * If the user asked for a shadow, we need to create one.  Do this instead
203     * of using the shadow parameter because the button widget is not part of
204     * the main widget and if the user asks for both buttons and a shadow, we
205     * need to create a shadow big enough for both widgets.  Create the shadow
206     * window using the widgets shadowWin element, so screen refreshes will draw
207     * them as well.
208     */
209    if (shadowWidget == TRUE)
210    {
211       /* Determine the height of the shadow window. */
212       shadowHeight = (buttonWidget == 0 ?
213 		      widget->boxHeight :
214 		      widget->boxHeight + buttonWidget->boxHeight - 1);
215 
216       /* Create the shadow window. */
217       widget->shadowWin = newwin (shadowHeight,
218 				  widget->boxWidth,
219 				  getbegy (widget->win) + 1,
220 				  getbegx (widget->win) + 1);
221 
222       /* Make sure we could have created the shadow window. */
223       if (widget->shadowWin != 0)
224       {
225 	 widget->shadow = TRUE;
226 
227 	 /*
228 	  * We force the widget and buttonWidget to be drawn so the
229 	  * buttonbox widget will be drawn when the widget is activated.
230 	  * Otherwise the shadow window will draw over the button widget.
231 	  */
232 	 drawCDKScroll (widget, ObjOf (widget)->box);
233 	 eraseCDKButtonbox (buttonWidget);
234 	 drawCDKButtonbox (buttonWidget, ObjOf (buttonWidget)->box);
235       }
236    }
237 
238    /* Check if the user wants to set the background of the widget. */
239    setCDKScrollBackgroundColor (widget, CDK_WIDGET_COLOR);
240 
241    /* Activate the scrolling list. */
242    answer = activateCDKScroll (widget, 0);
243 
244    /* If there were buttons, get the button selected. */
245    if (buttonWidget != 0)
246    {
247       selection = buttonWidget->currentButton;
248       destroyCDKButtonbox (buttonWidget);
249    }
250 
251    /* Shut down curses. */
252    destroyCDKScroll (widget);
253    destroyCDKScreen (cdkScreen);
254    endCDK ();
255 
256    /* Print out the answer. */
257    if (answer >= 0)
258    {
259       if (numberOutput == TRUE)
260       {
261 	 fprintf (fp, "%d\n", answer);
262       }
263       else
264       {
265 	 fprintf (fp, "%s\n", scrollList[answer]);
266       }
267    }
268    fclose (fp);
269 
270    CDKfreeStrings (scrollList);
271 
272    /* Exit with the answer. */
273    ExitProgram (selection);
274 }
275 
widgetCB(EObjectType cdktype GCC_UNUSED,void * object GCC_UNUSED,void * clientData,chtype key)276 static int widgetCB (EObjectType cdktype GCC_UNUSED,
277 		     void *object GCC_UNUSED,
278 		     void *clientData,
279 		     chtype key)
280 {
281    CDKBUTTONBOX *buttonbox = (CDKBUTTONBOX *)clientData;
282    (void) injectCDKButtonbox (buttonbox, key);
283    return (TRUE);
284 }
285