X11workbench Toolkit  1.0
X11workbench.c
1 // __ __ _ _ _ _ _ //
3 // \ \/ // |/ |__ __ ___ _ _ | | __| |__ ___ _ __ ___ | |__ ___ //
4 // \ / | || |\ \ /\ / // _ \ | '__|| |/ /| '_ \ / _ \| '_ \ / __|| '_ \ / __| //
5 // / \ | || | \ V V /| (_) || | | < | |_) || __/| | | || (__ | | | | _| (__ //
6 // /_/\_\|_||_| \_/\_/ \___/ |_| |_|\_\|_.__/ \___||_| |_| \___||_| |_|(_)\___| //
7 // //
8 // 'main' source for X11workbench //
9 // //
11 
12 /*****************************************************************************
13 
14  X11workbench - X11 programmer's 'work bench' application and toolkit
15  Copyright (c) 2010-2018 by Bob Frazier (aka 'Big Bad Bombastic Bob')
16  all rights reserved
17 
18  DISCLAIMER: The X11workbench application and toolkit software are supplied
19  'as-is', with no warranties, either implied or explicit.
20 
21  BSD-like license:
22 
23  There is no restriction as to what you can do with this software, so long
24  as you include the above copyright notice and DISCLAIMER for any distributed
25  work that is linked with, equivalent to, or derived from any portion of this
26  software, along with this paragraph that explains the terms of the license if
27  the source is also being made available. "Linked with" includes the use of a
28  portion of any of the source and/or header files, or their compiled binary
29  output, as a part of your application or library. A "derived work"
30  describes a work that uses a significant portion of the source files or the
31  algorithms that are included with this software.
32 
33  EXCLUSIONS
34 
35  Specifically excluded from this requirement are files that were generated by
36  the software, or anything that is included with the software that is part of
37  another package (such as files that were created or added during the
38  'configure' process).
39 
40  DISTRIBUTION
41 
42  The license also covers the use of part or all of any of the X11 workbench
43  toolkit source or header files in your distributed application, in source or
44  binary form. If you do not ship the source, the above copyright statement
45  and DISCLAIMER is still required to be placed in a reasonably prominent
46  place, such as documentation, splash screens, and/or 'about the application'
47  dialog boxes.
48 
49  Use and distribution are in accordance with GPL, LGPL, and/or the above
50  BSD-like license. See COPYING and README.md files for more information.
51 
52  Additionally, this software, in source or binary form, and in whole or in
53  part, may be used by explicit permission from the author, without the need
54  of a license.
55 
56  Additional information at http://sourceforge.net/projects/X11workbench
57  and http://bombasticbob.github.io/X11workbench/
58 
59 ******************************************************************************/
60 
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <stdarg.h>
64 #include <unistd.h>
65 #include <memory.h>
66 #include <string.h>
67 #include <strings.h>
68 #include <signal.h>
69 #include <time.h>
70 #include <errno.h>
71 #include <fcntl.h>
72 #include <sys/stat.h>
73 
74 // project includes
75 #include "X11workbench.h"
76 #include "gizzard.h"
77 #include "gdb_helper.h"
78 #include "refactor.h"
79 #include "context_help.h"
80 #include "resource_edit.h"
81 
82 // X11workbench toolkit library includes
83 #include "window_helper.h"
84 #include "pixmap_helper.h" // pixmap helpers, including pre-defined icons
85 #include "frame_window.h"
86 #include "edit_window.h" // edit (client) window
87 #include "dialog_window.h"
88 #include "file_help.h"
89 #include "conf_help.h"
90 #include "draw_text.h"
91 
92 // pixmap data
93 #include "application_icon.xpm" /* 19x19 icon presented to the OS for alt-tab etc. */
94 #include "icon_app.xpm" /* application icon that's the same size as the others, 36x36 */
95 #include "textfiledoc.xpm"
96 #include "newdoc.xpm"
97 #include "clangdoc.xpm"
98 #include "makefiledoc.xpm"
99 
100 
101 //#define NO_SPLASH /* temporary, later put it as a configure option - need to get 'gleam' to work better */
102 
103 //#define STRING "Hello, world"
104 //#define BORDER 32 /* was 1 */
105 //#define FONT "fixed"
106 
107 
108 #ifndef NO_SPLASH
109 #include "splash.xpm" // splash pixmap
110 #endif // NO_SPLASH
111 
112 
113 // copyright string '(c)' or the UTF8 symbol - if I support UTF8, use the circle-c version
114 #ifdef X_HAVE_UTF8_STRING
115 
116 // 11 bits U+07FF 110xxxxx 10xxxxxx
117 // A9 --> 10101001 --> 11000010 10101001 --> C2 A9
118 #define UTF8_COPYRIGHT "\xc2""\xa9"
119 
120 // TODO: any other UTF8-specific strings can be defined here
121 #endif // X_HAVE_UTF8_STRING
122 
123 
124 
125 
126 // function prototypes
127 
128 static int do_main(int argc, char *argv[], char *envp[]);
129 static void usage(void);
130 static void SetSignalHandlers(void);
131 static int MyWindowCallback(Window wID, XEvent *pEvent);
132 static int ApplicationPreferences(XClientMessageEvent *pEvent);
133 static int FileExitHandler(XClientMessageEvent *);
134 static int FileNewHandler(XClientMessageEvent *);
135 static int FileOpenHandler(XClientMessageEvent *);
136 static int FileSaveHandler(XClientMessageEvent *);
137 static int FileSaveUIHandler(WBMenu *, WBMenuItem *);
138 static int FileSaveAsHandler(XClientMessageEvent *);
139 static int FileSaveAsUIHandler(WBMenu *, WBMenuItem *);
140 static int FileSaveAllHandler(XClientMessageEvent *);
141 static int FileSaveAllUIHandler(WBMenu *, WBMenuItem *);
142 static int FileCloseHandler(XClientMessageEvent *);
143 
144 static int HelpAboutHandler(XClientMessageEvent *);
145 static int HelpContentsHandler(XClientMessageEvent *);
146 static int HelpContextHandler(XClientMessageEvent *);
147 
148 static int TabLeftHandler(XClientMessageEvent *);
149 static int TabRightHandler(XClientMessageEvent *);
150 static int TabMoveLeftHandler(XClientMessageEvent *);
151 static int TabMoveRightHandler(XClientMessageEvent *);
152 static int TabUIHandler(WBMenu *, WBMenuItem *);
153 
154 static int ToolBoxHandler(XClientMessageEvent *pEvent);
155 static int ToolBoxUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem);
156 
157 int DoFileOpen(WBFrameWindow *pMainFrame, const char *szFileName);
158 WBFILE_TYPE GetFileType(const char *szFileName); // return one of the WBFILE_TYPE constants
159 
160 
161 // global vars
162 int nCPU = 0;
163 
164 
165 int main(int argc, char *argv0[], char *envp0[])
166 {
167 int iRval = 1;
168 char **argv = argv0; // re-define as char ** so I can re-allocate it as needed
169 char **envp = envp0;
170 
171 
172  if(!(iRval = WBParseStandardArguments(&argc, &argv, &envp)))
173  {
174  iRval = do_main(argc, argv, envp);
175 
176  if(envp && envp != envp0)
177  {
178  WBFree(envp);
179  }
180 
181  if(argv && argv != argv0)
182  {
183  WBFree(argv);
184  }
185  }
186  else
187  {
188  if(iRval < 0)
189  {
190  usage();
191  }
192 
193  iRval = 1; // for now; later, return as-is?
194  }
195 
196  return iRval;
197 }
198 
199 
200 // global variables
201 
202 static Display *pX11Display = NULL; /* X server connection */
203 static WBFrameWindow *pMainFrame = NULL;
204 static XColor clrGreen;
205 
206 
207 Window GetFrameWindowID()
208 {
209  if(!pMainFrame)
210  {
211  return None;
212  }
213 
214  return pMainFrame->wID;
215 }
216 
218 // _____ __ ___ _ ____ _ _ //
219 // | ___| __ __ _ _ __ ___ ___ \ \ / (_)_ __ __| | _____ __ / ___|| |_ _ __ _ _ ___| |_ ___ //
220 // | |_ | '__/ _` | '_ ` _ \ / _ \ \ \ /\ / /| | '_ \ / _` |/ _ \ \ /\ / / \___ \| __| '__| | | |/ __| __/ __| //
221 // | _|| | | (_| | | | | | | __/ \ V V / | | | | | (_| | (_) \ V V / ___) | |_| | | |_| | (__| |_\__ \ //
222 // |_| |_| \__,_|_| |_| |_|\___| \_/\_/ |_|_| |_|\__,_|\___/ \_/\_/ |____/ \__|_| \__,_|\___|\__|___/ //
223 // //
225 
226 // application menu and the application menu handler structure 'main_menu_handlers'
227 
229 // default application menu - what I see when there's no open document
231 static char szAppMenu[]="1\n"
232  "_File\tpopup\t2\n"
233  "_Tools\tpopup\t5\n"
234  "\tseparator\n"
235  "_Help\tpopup\t3\n"
236  "\n"
237  "2\n"
238  "_New File\tIDM_FILE_NEW\tNew File\tCtrl+N\n"
239  "_Open File\tIDM_FILE_OPEN\tOpen File\tCtrl+O\n"
240  "\tseparator\n"
241  "_Preferences\tIDM_PREFERENCES\tApplication Preferences\tCtrl+P\n"
242  "\tseparator\n"
243  "E_xit\tIDM_FILE_EXIT\tClose Application\tAlt+F4\n"
244  "\n"
245  "3\n"
246  "_Contents\tIDM_HELP_CONTENTS\tHelp Contents\tAlt+F1\n"
247  "Conte_xt\tIDM_HELP_CONTEXT\tContext Help\tF1\n"
248  "\tseparator\n"
249  "_About X11workbench\tIDM_HELP_ABOUT\tAbout X11workbench\tAlt+F1\n"
250  "\n"
251  "5\n"
252  "_Toolbox\tIDM_TOOLBOX\tDisplay (or hide) the Toolbox\n"
253  "_Options\tIDM_TOOLS_OPTIONS\tDisplay Options Editor\n"
254  "\n";
255 
257 // edit menu - what I see when there's a child frame active
259 static char szEditMenu[]="1\n"
260  "_File\tpopup\t2\n"
261  "_Edit\tpopup\t4\n"
262  "_Tools\tpopup\t5\n"
263  "\tseparator\n"
264  "_Window\tpopup\t6\n"
265  "\tseparator\n"
266  "_Help\tpopup\t3\n"
267  "\n"
268  "2\n"
269  "_New File\t" FW_FILE_NEW_MENU "\tNew File\t" FW_FILE_NEW_ACCEL "\n"
270  "_Open File\t" FW_FILE_OPEN_MENU "\tOpen File\t" FW_FILE_OPEN_ACCEL "\n"
271  "_Save File\t" FW_FILE_SAVE_MENU "\tSave File\t" FW_FILE_SAVE_ACCEL "\n"
272  "Save _As\t" FW_FILE_SAVE_AS_MENU "\tSave As\t" FW_FILE_SAVE_AS_ACCEL "\n"
273  "Save A_ll\t" FW_FILE_SAVE_ALL_MENU "\tSave All\t" FW_FILE_SAVE_ALL_ACCEL "\n"
274  "\tseparator\n"
275  "_Close File\t" FW_FILE_CLOSE_MENU "\tClose File\tCtrl+F4\n"
276  "\tseparator\n"
277  "_Preferences\tIDM_PREFERENCES\tApplication Preferences\tCtrl+P\n"
278  "\tseparator\n"
279  "E_xit\tIDM_FILE_EXIT\tClose Application\tAlt+F4\n"
280  "\n"
281  "3\n"
282  "_Contents\tIDM_HELP_CONTENTS\tHelp Contents\tAlt+F1\n"
283  "Conte_xt\tIDM_HELP_CONTEXT\tContext Help\tF1\n"
284  "\tseparator\n"
285  "_About X11workbench\tIDM_HELP_ABOUT\tAbout X11workbench\tAlt+F1\n"
286  "\n"
287  "4\n"
288  "_Undo\t" FW_EDIT_UNDO_MENU "\tUn-do last action\t" FW_EDIT_UNDO_ACCEL "\n"
289  "_Redo\t" FW_EDIT_REDO_MENU "\tRe-do last action\t" FW_EDIT_REDO_ACCEL "\n"
290  "\tseparator\n"
291  "Cu_t\t" FW_EDIT_CUT_MENU "\tCut to Clipboard\t" FW_EDIT_CUT_ACCEL "\n"
292  "_Copy\t" FW_EDIT_COPY_MENU "\tCopy to Clipboard\t" FW_EDIT_COPY_ACCEL "\n"
293  "_Paste\t" FW_EDIT_PASTE_MENU "\tPaste from Clipboard\t" FW_EDIT_PASTE_ACCEL "\n"
294  "_Delete\t" FW_EDIT_DELETE_MENU "\tDelete selection\n"
295  "\tseparator\n"
296  "Select _All\t" FW_EDIT_SELECT_ALL_MENU "\tSelect All in context\t" FW_EDIT_SELECT_ALL_ACCEL "\n"
297  "Select _None\t" FW_EDIT_SELECT_NONE_MENU "\tSelect None in context\t" FW_EDIT_SELECT_NONE_ACCEL "\n"
298  "\tseparator\n"
299  "_Find\tIDM_EDIT_FIND\tFind within Document\tCtrl+F\n"
300  "Find Ne_xt\tIDM_EDIT_FIND_NEXT\tFind next occurence within Document\tCtrl+G\n"
301  "_Project Find\tIDM_EDIT_PROJ_FIND\tFind within entire project\tCtrl+Shift+F\n"
302  "Pro_ject Find Next\tIDM_EDIT_PROJ_FIND_NEXT\tFind next occurrence within entire project\tCtrl+Shift+G\n"
303  "\tseparator\n"
304  "Properties\t" FW_EDIT_PROPERTIES_MENU "\tFind next occurrence within entire project\t" FW_EDIT_PROPERTIES_ACCEL "\n"
305  "\n"
306  "5\n"
307  "_Toolbox\tIDM_TOOLBOX\tDisplay (or hide) the Toolbox\n"
308  "_Options\tIDM_TOOLS_OPTIONS\tDisplay Options Editor\n"
309  "\n"
310  "6\n"
311  "Tab _Left\tIDM_TAB_LEFT\tScroll Tab Left\tCtrl+Alt+PgUp\n"
312  "Tab _Right\tIDM_TAB_RIGHT\tScroll Tab Right\tCtrl+Alt+PgDown\n"
313  "\tseparator\n"
314  "Re-order Le_ft\tIDM_TAB_MOVE_LEFT\tScroll Tab Left\tCtrl+Alt+Shift+PgUp\n"
315  "Re-order R_ight\tIDM_TAB_MOVE_RIGHT\tScroll Tab Right\tCtrl+Alt+Shift+PgDown\n"
316  "\tseparator\n" // NOTE: I can add a list of windows here, with hotkeys
317  "\n";
318 
319 
320 // NOTES ON 'F' KEYS - these were compiled by someone else with respect to winders
321 // CTRL+ALT (and +SHIFT) any F key in X11 switches to a virtual desktop in console mode
322 //
323 // F1 - brings up a help window
324 // Alt - system menu
325 // F2 - in winders, rename selected object.
326 // Alt+Ctrl - in MS Orifice, opens documents library (don't do this in X11)
327 // F3 - in winders, open search box
328 // F4 - in winders XP, display address bar list (or similar)
329 // Alt - close application/window
330 // F5 - window refresh/update (such as in Firefox)
331 // F6 - cycle through screen elements of a window
332 // F7 - turn on/off "caret mode" in Firefox; in MS Weird, spell/grammar checking
333 // F8 - extend selection (MS orifice)
334 // F9 - update fields (MS orifice, particularly ExHell)
335 // F10 - activates the menu
336 // SHIFT - pops up a context menu (in X11 at least) like a right-click would
337 // ALT - in X11, maximize/normal (retaining window decorations)
338 // F11 - toggle between "true full-screen" (no window decorations) and normal [works in gnome/mate as well]
339 // F12 - opens 'save as' dialog (in MS Orifice)
340 
341 
342 
343 
344 // menu handler, similar to what MFC does
345 // in theory I can swap in a new menu handler when the window focus changes
346 // this is the DEFAULT handler, when no 'child frame' has the focus. It also handles
347 // all of the OTHER menu stuff, out of convenience
348 
349 FW_MENU_HANDLER_BEGIN(main_menu_handlers)
350  FW_MENU_HANDLER_ENTRY("IDM_FILE_EXIT",FileExitHandler,NULL)
351  FW_MENU_HANDLER_ENTRY("IDM_FILE_NEW",FileNewHandler,NULL)
352  FW_MENU_HANDLER_ENTRY("IDM_FILE_OPEN",FileOpenHandler,NULL)
353  FW_MENU_HANDLER_ENTRY("IDM_FILE_SAVE",FileSaveHandler,FileSaveUIHandler)
354  FW_MENU_HANDLER_ENTRY("IDM_FILE_SAVE_AS",FileSaveAsHandler,FileSaveAsUIHandler)
355  FW_MENU_HANDLER_ENTRY("IDM_FILE_SAVE_ALL",FileSaveAllHandler,FileSaveAllUIHandler)
356 
357  FW_MENU_HANDLER_ENTRY("IDM_FILE_CLOSE",FileCloseHandler,NULL) // TODO: do a UI handler?
358 
359  FW_MENU_HANDLER_ENTRY("IDM_PREFERENCES", ApplicationPreferences,NULL)
360 
361  FW_MENU_HANDLER_ENTRY("IDM_TOOLBOX",ToolBoxHandler,ToolBoxUIHandler)
362 
363  FW_MENU_HANDLER_ENTRY("IDM_TAB_LEFT",TabLeftHandler, TabUIHandler)
364  FW_MENU_HANDLER_ENTRY("IDM_TAB_RIGHT",TabRightHandler, TabUIHandler)
365  FW_MENU_HANDLER_ENTRY("IDM_TAB_MOVE_LEFT",TabMoveLeftHandler, TabUIHandler)
366  FW_MENU_HANDLER_ENTRY("IDM_TAB_MOVE_RIGHT",TabMoveRightHandler, TabUIHandler)
367 
368  FW_MENU_HANDLER_ENTRY("IDM_HELP_ABOUT",HelpAboutHandler,NULL)
369  FW_MENU_HANDLER_ENTRY("IDM_HELP_CONTEXT",HelpContextHandler,NULL)
370  FW_MENU_HANDLER_ENTRY("IDM_HELP_CONTENTS",HelpContentsHandler,NULL)
371 
372 #if 0
373  // additional EDIT MENU HANDLERS
374 
375  FW_MENU_HANDLER_ENTRY("IDM_EDIT_FIND",EditFindHandler,EditFindUIHandler)
376  FW_MENU_HANDLER_ENTRY("IDM_EDIT_FIND_NEXT",EditFindNextHandler,EditFindNextUIHandler)
377  FW_MENU_HANDLER_ENTRY("IDM_EDIT_PROJ_FIND",EditProjFindHandler,EditProjFindUIHandler)
378  FW_MENU_HANDLER_ENTRY("IDM_EDIT_PROJ_FIND_NEXT",EditProjFindNextHandler,EditProjFindNextUIHandler)
379 #endif // 0
380 
382 
383 
384 
385 // end of global variables
386 
387 
388 
389 static void usage(void)
390 {
391  fputs("X11workbench - Copyright (c) 2010-2018 by S.F.T. Inc. - all rights reserved\n\n"
392  "Usage: X11workbench [options] filename [filename [...]]\n"
393  " where 'filename' represents one or more files or workspaces to be opened on startup\n"
394  "\n"
395  "Standard X11workbench Options\n"
396  "-h display this message\n"
397 #ifndef NO_DEBUG
398  "-d dump settings on startup\n"
399 #endif // NO_DEBUG
400 #ifndef NO_SPLASH
401  "--nosplash Skip the 'splash' screen on startup\n"
402 #endif // !NO_SPLASH
403  "\n", stderr);
404 
405  WBToolkitUsage();
406 }
407 
408 static void get_min_window_height_width(int *piMinHeight, int *piMinWidth)
409 {
410 #if 0 // old code, consider removing this
411 
412  // DEMO CODE - using the 'STRING' size, calculate the minimum width/height and pass that
413  // as parameters to WBInitSizeHints
414 
415  // calculating the actual font height for the default font
416 
417  unsigned long fth = WBGetDefaultFont()->max_bounds.ascent // default font height
418  + WBGetDefaultFont()->max_bounds.descent;
419 
420  // the pad and border are part of the 'hello world' text and green border displayed for the demo
421  unsigned long pad = 32 /*BORDER*/; // font padding (only used here) [TODO: fix this better]
422  unsigned long bw = 1; // border width (only used here)
423 
424  *piMinHeight = fth + pad * 2 + bw * 2;
425  *piMinWidth = XTextWidth(WBGetDefaultFont(), // minimum width (based on text width)
426  STRING,
427  strlen(STRING)) + pad * 2 + bw * 2;
428 #endif // 0
429 
430  if(*piMinHeight)
431  {
432  *piMinHeight = 360; // for now just hard-code it
433  }
434 
435  if(*piMinWidth)
436  {
437  *piMinWidth = 512; // for now just hard-code it
438  }
439 }
440 
441 
443 // do_main - initialization, loop, termination
444 // (the classic top-down model)
446 
447 int do_main(int argc, char *argv[], char *envp[])
448 {
449 //unsigned long fg, bg, bd; /* Pixel values */
450 XEvent event; /* Event received */
451 XSizeHints xsh; /* Size hints for window manager */
452 //XSetWindowAttributes xswa; /* Temporary Set Window Attribute struct */
453 char szGreen[]="#00FF00"; // text color for green
454 Colormap colormap;
455 int i1, iMinHeight, iMinWidth;
456 #ifndef NO_DEBUG
457 int iDebugDumpConfig = 0;
458 #endif // NO_DEBUG
459 #ifndef NO_SPLASH
460 int bNoSplash = 0;
461 #endif // !NO_SPLASH
462 
463 
464  // as opposed to 'getarg' this method is system independent
465  // some POSIX systems don't support 'getarg' correctly
466  // TODO: put it in platform_helper.[ch] and use HAVE_GETARG
467 
468  while(argc > 1)
469  {
470  if(argv[1][0] != '-' || !argv[1][1])
471  {
472  if(argv[1][0] == '-')
473  {
474  argv++;
475  argc--;
476  }
477 
478  break;
479  }
480 
481  if(argv[1][1] == '-') // a double-dash
482  {
483  // double-dash items go here. only 'one per'
484 
485  if(!strcmp(&(argv[1][2]), "nosplash"))
486  {
487  bNoSplash = 1;
488  goto next_argument;
489  }
490 
491  fprintf(stderr, "Unrecognized option \"%s\"\n", argv[1]);
492  usage();
493 
494  return 1; // illegal argument
495  }
496 
497  for(i1=1; argv[1][i1]; i1++)
498  {
499  if(argv[1][i1] == 'h' ||
500  argv[1][i1] == 'H')
501  {
502  usage();
503  return 0;
504  }
505 #ifndef NO_DEBUG
506  else if(argv[1][i1] == 'd')
507  {
508  iDebugDumpConfig = 1;
509  }
510 #endif // NO_DEBUG
511  else
512  {
513  fprintf(stderr, "Unrecognized option \"-%c\"\n", argv[1][i1]);
514 
515  usage();
516  return 1;
517  }
518  }
519 
520 next_argument:
521  argv++;
522  argc--;
523  }
524 
525  // initialization - set signal handlers, open display, etc.
526 
527  SetSignalHandlers();
528 
529  pX11Display = WBInit(NULL); // initialize X11 Work Bench Toolkit and obtain Display pointer
530  if(!pX11Display)
531  {
532  return 1; // can't open display, so byby!
533  }
534 
535  PXM_RegisterAppIcons(icon_app_xpm, application_icon_xpm);
536 
537 
538  nCPU = WBCPUCount(); // get # of CPUs
539 
540 
541 #ifndef NO_DEBUG
542  // This DEBUG section dumps the config data when theh '-d' option was specified on the command line.
543  // it requires a Display object so I must do it HERE. Then I can call WBExit and bail out.
544 
545  if(iDebugDumpConfig)
546  {
547  CHDumpConfig();
548 
549  WBExit();
550  return 0;
551  }
552 #endif // NO_DEBUG
553 
554  // SUPPLEMENTAL INITIALIZATION STUFF
555 
556  // color selection
557 
558 // bd = WhitePixel(pX11Display, DefaultScreen(pX11Display)); // border
559 // bg = BlackPixel(pX11Display, DefaultScreen(pX11Display)); // background
560 // fg = WhitePixel(pX11Display, DefaultScreen(pX11Display)); // foreground
561 
562  // dont' forget the colormap
563 
564  colormap = WBDefaultColormap(pX11Display);
565 
566  // additional allocated colors - in this case, GREEN
567  XParseColor(pX11Display, colormap, szGreen, &clrGreen);
568  XAllocColor(pX11Display, colormap, &clrGreen); // NOTE: do I need 'XFreeColors' for 'clrGreen' ?
569 
570 #ifndef NO_SPLASH
571 
572 
573  if(!bNoSplash)
574  {
575  char *pCopyright = WBCopyString(
576 #ifdef UTF8_COPYRIGHT
577  "Copyright " UTF8_COPYRIGHT " 2010-2018 by Big Bad Bombastic Bob\nAll Rights Reserved" // text string with unicode char in it U+00A9
578 #else // UTF8_COPYRIGHT
579  "Copyright (c) 2010-2018 by Big Bad Bombastic Bob\nAll Rights Reserved"
580 #endif // UTF8_COPYRIGHT
581  );
582 
583  if(pCopyright && nCPU > 0)
584  {
585  char tbuf[32];
586 
587  snprintf(tbuf, sizeof(tbuf), "%d **", nCPU);
588  WBCatString(&pCopyright, "\n** CPU Count: ");
589  if(pCopyright)
590  {
591  WBCatString(&pCopyright, tbuf);
592  }
593  }
594 
595  if(pCopyright)
596  {
597  DLGSplashScreen(splash_xpm,
598  pCopyright, WhitePixel(pX11Display, DefaultScreen(pX11Display))); // white text
599 
600  WBFree(pCopyright);
601  }
602  else
603  {
604  DLGSplashScreen(splash_xpm,
605  "Copyright (c) 2010-2018 by Big Bad Bombastic Bob\nAll Rights Reserved", // 1 or 2 lines only
606  WhitePixel(pX11Display, DefaultScreen(pX11Display))); // white text
607  }
608  }
609 #endif // NO_SPLASH
610 
611  get_min_window_height_width(&iMinHeight, &iMinWidth);
612 
613  // I will need to center the new window, so figure out how to do that
614 
615  WBInitSizeHints(&xsh, // pointer to XSizeHints
616  pX11Display, // Display pointer
617  iMinHeight, // minimum height (based on font height)
618  iMinWidth); // minimum width
619 
620 // // init window attributes
621 //
622 // WBInitWindowAttributes(&xswa, // attribute structure
623 // bd, // border pixel color
624 // bg, // background window color
625 // colormap, // colormap
626 // CenterGravity); // gravity
627 
628  // create frame window object (always uses default display)
629 
630  pMainFrame = FWCreateFrameWindow("X11workbench", // title
631  ID_APPLICATION, // icon
632  szAppMenu, // application menu
633  xsh.x, xsh.y, // position
634  xsh.width, xsh.height, // size
635  MyWindowCallback, // callback
636  WBFrameWindow_APP_WINDOW // flags and attributes
639 
640  if(!pMainFrame)
641  {
642  WB_ERROR_PRINT("%s - Unable to create main frame window\n", __FUNCTION__);
643 
644  WBExit();
645  return 2;
646  }
647 
648 // {
649 // const char *pNothing = szEditMenu; // to avoid certain warnings - remove later
650 //
651 // pNothing = pNothing;
652 // }
653 
654  // assign menu handlers to the frame window (this does the callback functions for me)
655  // this is part of the frame window functionality for the DEFAULT menu
656 
657  FWSetMenuHandlers(pMainFrame, main_menu_handlers);
658 
659 
660  // open files specifed on command line
661 
662  // TODO: if project file specified, open files based on project state
663  // Otherwise, open as "single file"
664 
665  WBBeginWaitCursor(pMainFrame->wID);
666 
667  while(argc > 1)
668  {
669  // TODO: is it a project file?
670 
671  DoFileOpen(pMainFrame, argv[1]);
672 
673  argc--;
674  argv++;
675  }
676 
677  WBEndWaitCursor(pMainFrame->wID);
678 
679  if(FWGetNumContWindows(pMainFrame) > 0) // if I opened anything, set focus to first one
680  {
681  FWSetFocusWindowIndex(pMainFrame, 0);
682  }
683 
684 
685 
686  //=========================
687  // MAIN MESSAGE LOOP
688  //=========================
689 
690  while (!bQuitFlag /*1*/)
691  {
692  if(!WBCheckGetEvent(pX11Display, &event))
693  {
694  // SLEEP if no event while in message loop (function returns without blocking)
695  // otherwise I can do background tasks during this loop iteration.
696 
697  // if I have NO BACKGROUND PROCESSES to do, I can use 'WBWaitForEvent'
698 
699  if(1)
700  {
701  WBWaitForEvent(pX11Display);
702  }
703  else
704  {
705  WBDelay(100); // delay 100 microseconds (0.1 milliseconds)
706  }
707 
708  continue; // skip the 'WBDispatch' since there was no event
709  }
710 
711  WBDispatch(&event);
712  }
713 
714  if(pMainFrame)
715  {
716  WBDestroyWindow(pMainFrame->wID);
717  }
718 
719  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Application,
720  "%s - Application about to exit\n", __FUNCTION__);
721 
722  WBExit();
723 
724  return 0;
725 }
726 
727 
728 
730 // CALLBACK FUNCTIONS
732 
733 extern void TestFunc(Display *pDisplay, GC gc, Window wID, int iX, int iY);
734 
735 static int MyWindowCallback(Window wID, XEvent *pEvent)
736 {
737 XWindowAttributes xwa; /* Temp Get Window Attribute struct */
738 int iRval = 0;
739 
740  /*
741  * On the last of each group of Expose events, repaint the entire
742  * window. See Section 8.4.5.1.
743  */
744 
745  if(pEvent->type == DestroyNotify &&
746  pEvent->xdestroywindow.window == wID)
747  {
748  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Application,
749  "%s - DestroyNotify\n", __FUNCTION__);
750 
751  if(pMainFrame && pMainFrame->wID == wID)
752  {
753  pMainFrame = NULL; // because I'm destroying it
754  }
755 
756  return 0; // let remaining default processing happen
757  }
758 
759  if(pEvent->type == ClientMessage &&
760  pEvent->xclient.message_type == aQUERY_CLOSE)
761  {
762  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Application,
763  "%s - QUERY_CLOSE\n", __FUNCTION__);
764 
765  if(pEvent->xclient.data.l[0]) // close is imminent if I return 0
766  {
767  if(pMainFrame && pMainFrame->wID == wID)
768  {
769  pMainFrame = NULL; // because I'm destroying it
770  }
771  }
772 
773  return 0; // "ok to close" (let frame window handle anything else)
774  }
775 
776  if (pEvent->type == Expose && pEvent->xexpose.count == 0)
777  {
778  GC gc;
779  WB_GEOM geom;
780 
781 // NOTE: this is managed by the toolkit
782 // /*
783 // * Remove any other pending Expose events from the queue to
784 // * avoid multiple repaints. See Section 8.7.
785 // */
786 // while(!bQuitFlag && XCheckTypedWindowEvent(pX11Display, wID, Expose, pEvent))
787 // ;
788 //
789 // if(bQuitFlag)
790 // {
791 // iRval = 1;
792 // WB_DEBUG_PRINT(DebugLevel_Light | DebugSubSystem_Application,
793 // "%s - Quit flag set - returning %d\n", __FUNCTION__, iRval);
794 //
795 // return iRval; // let default processing happen
796 // }
797 
798  /*
799  * Find out how big the window is now, so that we can center
800  * the text in it.
801  */
802  if(XGetWindowAttributes(pX11Display, wID, &xwa) == 0)
803  {
804  WB_ERROR_PRINT("%s - Cannot get correct attributes for window! Returning %d\n",
805  __FUNCTION__, iRval);
806  return iRval;
807  }
808 
809  gc = WBBeginPaint(wID, &(pEvent->xexpose), &geom); // begin paint, get a gc for it
810 
811  if(gc == None)
812  {
813  WB_ERROR_PRINT("%s - Cannot get graphics context for paint\n", __FUNCTION__);
814  return 0; // not handled
815  }
816 
817  WBClearWindow(wID, gc); // does the erase background intelligently
818 
819 
820 #ifdef DISPLAY_HELLO_WORLD
821  {
822  XFontStruct *pFont;
823  int x, y, x0, y0, x1, y1;
824 
825  pFont = WBGetWindowFontStruct(wID);
826  if(!pFont)
827  {
828  WB_ERROR_PRINT("%s - No font - returning %d\n", __FUNCTION__, iRval);
829  return iRval; // let default processing happen
830  }
831 
832  x0 = XTextWidth(pFont, STRING, strlen(STRING));
833  y0 = pFont->max_bounds.ascent
834  - pFont->max_bounds.descent;
835 
836  x = (xwa.width - x0) / 2;
837  y = (xwa.height + pFont->max_bounds.ascent
838  - pFont->max_bounds.descent) / 2;
839 
840  // adjust new values for X0 and y0 to surround x and y
841 
842  x1 = x + x0 + 20;
843  x0 = x - 20;
844 
845  y1 = y + pFont->max_bounds.descent + 20;
846  y0 = y - y0 - 20;
847 
848  /*
849  * Fill the window with the background color, and then paint
850  * the centered string.
851  */
852 
853  XSetForeground(pX11Display, gc, WBGetWindowFGColor(wID));
854  XDrawString(pX11Display, wID, gc, x, y, STRING, strlen(STRING));
855 
856  XSetForeground(pX11Display, gc, clrGreen.pixel);
857 
858  // draw my green rectangle
859 
860  XDrawRectangle(pX11Display, wID, gc, x0, y0, x1 - x0, y1 - y0);
861  XSetForeground(pX11Display, gc, WBGetWindowFGColor(wID)); // restore it at the end
862  }
863 #endif // DISPLAY_HELLO_WORLD
864 
865 // TestFunc(pX11Display, gc, wID, x0 - 32, y0 - 32); // TEMPORARY
866 
867  WBEndPaint(wID, gc); // done now [free resources]
868 
869  iRval = 1; // processed
870 
871  WB_DEBUG_PRINT(DebugLevel_Excessive | DebugSubSystem_Window,
872  "%s - Expose returning %d\n", __FUNCTION__, iRval);
873 
874  return iRval; // let default processing happen
875  }
876 
877  // menu events
878  if(pEvent->type == ClientMessage && pEvent->xclient.message_type == aMENU_COMMAND)
879  {
880  iRval = 1;
881 
882  WB_DEBUG_PRINT(DebugLevel_Light | DebugSubSystem_Window | DebugSubSystem_Menu | DebugSubSystem_Event,
883  "%s - detecting main window menu event %ld\n", __FUNCTION__,
884  pEvent->xclient.data.l[0]);
885  }
886 
887  WB_DEBUG_PRINT(DebugLevel_Excessive | DebugSubSystem_Window,
888  "%s - Returning %d\n", __FUNCTION__, iRval);
889 
890  return iRval; // let default processing happen if zero, else 'processed'
891 }
892 
893 
895 // //
896 // _ _ _ _ _ _ _ _____ _ _ //
897 // | | | || |_ (_)| |(_)| |_ _ _ | ___|_ _ _ __ ___ | |_ (_) ___ _ __ ___ //
898 // | | | || __|| || || || __|| | | | | |_ | | | || '_ \ / __|| __|| | / _ \ | '_ \ / __| //
899 // | |_| || |_ | || || || |_ | |_| | | _| | |_| || | | || (__ | |_ | || (_) || | | |\__ \ //
900 // \___/ \__||_||_||_| \__| \__, | |_| \__,_||_| |_| \___| \__||_| \___/ |_| |_||___/ //
901 // |___/ //
902 // //
904 
905 // 'DoFileOpen()' - API to open a file and create a child frame derived tab for it
906 
907 int DoFileOpen(WBFrameWindow *pMainFrame, const char *szFileName)
908 {
909 WBFILE_TYPE ft;
910 WBChildFrame *pCF;
911 int iTab, iLineEnd;
912 
913 
914  if(!pMainFrame || !szFileName || !*szFileName)
915  {
916  return -1;
917  }
918 
919  pCF = NULL; // as a flag for later, make sure it's NULL
920 
921  // create a new tab in the frame window using the correct type of child window
922 
923  ft = GetFileType(szFileName);
924 
925  if(ft == WBFILE_TYPE_PROJECT)
926  {
928  "File Open", "'File _Open' project file not (yet) supported");
929  }
930  else if(ft == WBFILE_TYPE_RESOURCE)
931  {
933  "File Open", "'File _Open' resource file not (yet) supported");
934  }
935  else if(ft == WBFILE_TYPE_PIXMAP)
936  {
938  "File Open", "'File _Open' pixmap file not (yet) supported");
939  }
940  else if(ft == WBFILE_TYPE_DIALOG)
941  {
943  "File Open", "'File _Open' dialog resource file not (yet) supported");
944  }
945  else if(ft == WBFILE_TYPE_MENU)
946  {
948  "File Open", "'File _Open' menu resource file not (yet) supported");
949  }
950  else if(ft == WBFILE_TYPE_TOOLBAR)
951  {
953  "File Open", "'File _Open' toolbar resource file not (yet) supported");
954  }
955  else
956  {
957  // All other files are assumed to be text files and will create a WBEditWindow as a new tab.
958 
959  // 1st, create a new 'WBEditWindow', attaching it to the frame
960 
961  WBEditWindow *pEW = WBCreateEditWindow(pMainFrame, NULL, szEditMenu, main_menu_handlers, 0);
962 
963  if(!pEW)
964  {
966  "File Open", "'File _Open' unable to create edit window");
967  }
968  else
969  {
970  pCF = &(pEW->childframe);
971 
972  WBBeginWaitCursor(pCF->wID);
973 
974  // next, load the contents of the file into it
975 
976  if(WBEditWindowLoadFile(pEW, szFileName))
977  {
979  "File Open", "'File _Open' unable to read file into edit window");
980  }
981  }
982 
983  // TODO: set up a few things based on the file type
984  // a) default line ending
985  // b) default unicode/UTF-8 [as required]
986  // c) default tab handling
987  // d) color highlighting
988  // etc.
989 
990  // TODO: read this info from the config file, with defaults specified
991  // by the utility functions.
992 
993 
994  iLineEnd = GetDefaultLineEnding(ft); // read line ending info from config file, default to this
995  iTab = GetDefaultTabSetting(ft); // read tab info from config file, default to this
996 
997  // TODO: scan file to see what the line endings REALLY are?
998  pEW->xTextObject.vtable->set_linefeed(&(pEW->xTextObject), iLineEnd);
999 
1000  if(ft == WBFILE_TYPE_MAKEFILE ||
1001  ft == WBFILE_TYPE_AUTOCONF)
1002  {
1004  FileType_MAKEFILE | FileType_HARDTAB); // always hard tabs
1005  }
1006  else if(ft == WBFILE_TYPE_CPROG || ft == WBFILE_TYPE_CPP ||
1007  ft == WBFILE_TYPE_CHEADER || ft == WBFILE_TYPE_SHELL ||
1008  ft == WBFILE_TYPE_PYTHON || ft == WBFILE_TYPE_PERL ||
1009  ft == WBFILE_TYPE_ASM || ft == WBFILE_TYPE_JAVA ||
1010  ft == WBFILE_TYPE_JS || ft == WBFILE_TYPE_PHP ||
1011  ft == WBFILE_TYPE_ARDUINO)
1012  {
1013  // programming languages
1014  if(iTab < 0) // hard tabs
1015  {
1017  FileType_PROGRAM | FileType_HARDTAB); // use hard tabs
1018  }
1019  else
1020  {
1022  FileType_PROGRAM); // use spaces
1023  }
1024  }
1025  else if(ft == WBFILE_TYPE_HTML ||
1026  ft == WBFILE_TYPE_XML)
1027  {
1028  // programming languages
1029  if(iTab < 0) // hard tabs
1030  {
1032  FileType_XML | FileType_HARDTAB); // use hard tabs
1033  }
1034  else
1035  {
1037  FileType_XML); // use spaces
1038  }
1039  }
1040  else // plain text
1041  {
1042  if(iTab < 0) // hard tabs
1043  {
1045  FileType_PLAIN_TEXT | FileType_HARDTAB); // use hard tabs
1046  }
1047  else
1048  {
1050  FileType_PLAIN_TEXT); // use spaces
1051  }
1052  }
1053 
1054  pEW->xTextObject.vtable->set_tab(&(pEW->xTextObject), abs(iTab));
1055  }
1056 
1057  if(pCF) // did I create the new child frame??
1058  {
1059  const char *pDisplayName;
1060 
1061  // display file name with no path info within tab
1062  pDisplayName = szFileName + strlen(szFileName);
1063 
1064  while(pDisplayName > szFileName && *(pDisplayName - 1) != '/')
1065  {
1066  pDisplayName--;
1067  }
1068 
1069  FWSetChildFrameDisplayName(pCF, pDisplayName);
1070 
1071  WBEndWaitCursor(pCF->wID);
1072  }
1073 
1074  return pCF ? 0 : -1;
1075 }
1076 
1077 
1078 WBFILE_TYPE GetFileType(const char *szFileName) // return one of the WBFILE_TYPE constants
1079 {
1080 const char *pFN, *pExt;
1081 
1082  pFN = pExt = szFileName + strlen(szFileName);
1083 
1084  while(pFN > szFileName && *(pFN - 1) != '/')
1085  {
1086  pFN--;
1087  }
1088 
1089  while(pExt > szFileName && *(pExt - 1) != '.')
1090  {
1091  pExt--;
1092  }
1093 
1094  if(pExt <= szFileName)
1095  {
1096  pExt = NULL; // no extension
1097  }
1098 
1099  // TODO: don't just check the extension, read the first few lines, check for
1100  // invalid/unprintable characters, etc.
1101 
1102  if(pExt && !strcasecmp("makefile", pExt))
1103  {
1104  return WBFILE_TYPE_MAKEFILE;
1105  }
1106  else if(!pExt)
1107  {
1108  // TODO: look for hash-bang
1109  }
1110  else if(!strcasecmp("mk", pExt)) // '.mk' '.Mk' or '.MK' (or even '.mK') extension
1111  {
1112  return WBFILE_TYPE_MAKEFILE;
1113  }
1114  else if(!strcasecmp("h", pExt)) // also allow case-insensitive naming, in case 'windows'
1115  {
1116  return WBFILE_TYPE_MAKEFILE;
1117  }
1118  else if(!strcasecmp("c", pExt)) // also allow case-insensitive naming, in case 'windows'
1119  {
1120  return WBFILE_TYPE_CPROG;
1121  }
1122  else if(!strcasecmp("h", pExt)) // also allow case-insensitive naming, in case 'windows'
1123  {
1124  return WBFILE_TYPE_CHEADER;
1125  }
1126  else if(!strcasecmp("cpp", pExt)) // also allow case-insensitive naming, in case 'windows'
1127  {
1128  return WBFILE_TYPE_CPP;
1129  }
1130  else if(!strcmp("java", pExt)) // for now I only do the lower-case extension naming here
1131  {
1132  return WBFILE_TYPE_JAVA;
1133  }
1134  else if(!strcmp("js", pExt)) // for now I only do the lower-case extension naming here
1135  {
1136  return WBFILE_TYPE_JS;
1137  }
1138  else if(!strcmp("pl", pExt)) // for now I only do the lower-case extension naming here
1139  {
1140  return WBFILE_TYPE_PERL;
1141  }
1142  else if(!strcasecmp("py", pExt)) // also allow case-insensitive naming, in case 'windows'
1143  {
1144  return WBFILE_TYPE_PYTHON;
1145  }
1146  else if(!strcmp("xpm", pExt))
1147  {
1148  return WBFILE_TYPE_PIXMAP;
1149  }
1150  else if(!strcmp("ac", pExt) || !strcmp("am", pExt))
1151  {
1152  return WBFILE_TYPE_AUTOCONF;
1153  }
1154  else if(!strcasecmp("xwb", pExt)) // also allow case-insensitive naming, in case 'windows'
1155  {
1156  return WBFILE_TYPE_PROJECT;
1157  }
1158  else if(!strcasecmp("xwbrc", pExt)) // also allow case-insensitive naming, in case 'windows'
1159  {
1160  return WBFILE_TYPE_RESOURCE;
1161  }
1162  else if(!strcasecmp("xwbdlg", pExt)) // also allow case-insensitive naming, in case 'windows'
1163  {
1164  return WBFILE_TYPE_DIALOG;
1165  }
1166  else if(!strcasecmp("xwbmenu", pExt)) // also allow case-insensitive naming, in case 'windows'
1167  {
1168  return WBFILE_TYPE_MENU;
1169  }
1170  else if(!strcasecmp("xwbbar", pExt)) // also allow case-insensitive naming, in case 'windows'
1171  {
1172  return WBFILE_TYPE_TOOLBAR;
1173  }
1174  else if(!strcmp("sh", pExt))
1175  {
1176  return WBFILE_TYPE_SHELL;
1177  }
1178  else if(!strcasecmp("php", pExt)) // also allow case-insensitive naming, in case 'windows'
1179  {
1180  return WBFILE_TYPE_PHP;
1181  }
1182  else if(!strcasecmp("htm", pExt) || !strcasecmp("html", pExt)) // also allow case-insensitive naming, in case 'windows'
1183  {
1184  return WBFILE_TYPE_HTML;
1185  }
1186  else if(!strcasecmp("xml", pExt)) // also allow case-insensitive naming, in case 'windows'
1187  {
1188  return WBFILE_TYPE_XML;
1189  }
1190  else if(!strcasecmp("pde", pExt) || !strcasecmp("ino", pExt)) // also allow case-insensitive naming, in case 'windows'
1191  {
1192  return WBFILE_TYPE_ARDUINO; // arduino script may require some additional 'special help'
1193  }
1194 
1195 
1196  return WBFILE_TYPE_TEXT; // default
1197 }
1198 
1199 
1200 int GetDefaultTabSetting(WBFILE_TYPE nFileType)
1201 {
1202  if(nFileType == WBFILE_TYPE_MAKEFILE || nFileType == WBFILE_TYPE_AUTOCONF)
1203  {
1204  return -8; // hard tab, 8 bytes (always)
1205  }
1206 // else if(nFileType == WBFILE_TYPE_HTML ||
1207 // nFileType == WBFILE_TYPE_XML)
1208 // {
1209 // // TODO: read from config
1210 //
1211 // return 4; // 4 bytes, soft tab
1212 // }
1213 
1214  // TODO: read file-type from config and default tab size
1215 
1216 
1217  return 4; // 4 bytes, soft tab (the default)
1218 }
1219 
1220 int GetDefaultLineEnding(WBFILE_TYPE nFileType)
1221 {
1222  if(nFileType == WBFILE_TYPE_HTML ||
1223  nFileType == WBFILE_TYPE_XML)
1224  {
1225  return LineFeed_CRLF; // by convention for these (TODO: check settings?)
1226  }
1227  else if(nFileType == WBFILE_TYPE_MAKEFILE || nFileType == WBFILE_TYPE_AUTOCONF)
1228  {
1229  // TODO: what about windows nmake files?
1230 
1231  return LineFeed_NEWLINE;
1232  }
1233 
1234  return LineFeed_DEFAULT;
1235 }
1236 
1237 const char *GetFileTypeDesc(WBFILE_TYPE nFileType)
1238 {
1239 static const char * const aszDesc[] =
1240 {
1241  "None",
1242  "Text",
1243  "C Program Source",
1244  "C++ Program Source",
1245  "C/C++ Header File",
1246  "Make File",
1247  "Auto-conf File",
1248  "XWB Project File"
1249  "Resource File",
1250  "Pixmap File",
1251  "Dialog Resource",
1252  "Menu Resource",
1253  "Toolbar Resource",
1254  "Shell Program",
1255  "Python Program",
1256  "Perl Program"
1257  "Assembly Program Source",
1258  "HTML Source",
1259  "XML Data",
1260  "Java Program Source",
1261  "JavaScript Program",
1262  "PHP Program",
1263  "Arduino Script"
1264 };
1265 
1266 
1267  if(WBFILE_TYPE_LAST > sizeof(aszDesc)/sizeof(aszDesc[0]))
1268  {
1269  WB_WARN_PRINT("WARNING: %s 'aszDesc' array is too small\n", __FUNCTION__);
1270  }
1271 
1272  if((int)nFileType >= sizeof(aszDesc)/sizeof(aszDesc[0]) || (int)nFileType < 0)
1273  {
1274  return NULL;
1275  }
1276 
1277  return aszDesc[(int)nFileType];
1278 }
1279 
1280 
1281 const char *GetFileTypeHighlightInfo(WBFILE_TYPE nFileType)
1282 {
1283  if(nFileType == WBFILE_TYPE_CPROG ||
1284  nFileType == WBFILE_TYPE_CPP ||
1285  nFileType == WBFILE_TYPE_CHEADER ||
1286  nFileType == WBFILE_TYPE_ARDUINO)
1287  {
1288  static const char szC[]= // parameter: keyword list <LF> where keyword list is one or more words that might need to be quoted
1289  "Language: C/C++\n" // text of language style name
1290  "Comment: //\n" // text that begins single-line comment
1291  "CommentBlockBegin: /*\n" // text that begins comment block
1292  "CommentBlockEnd: */\n" // text that ends comment block
1293  "ScopeBegin: {\n" // text that begins scope
1294  "ScopeEnd: }\n" // text that ends scope
1295  "TextBegin: \"\n" // character that begins a block of text
1296  "TextEnd: \"\n" // character that ends a block of text
1297  "AltTextBegin:\n" // alternate character that begins a block of text
1298  "AltTextEnd:\n" // alternate character that ends a block of text
1299  "CharBegin: '\n" // character that begins a single character or block of text
1300  "CharEnd: '\n" // character that ends a single character or block of text
1301  "AltCharBegin:\n" // alternate character that begins a single character or block of text
1302  "AltCharEnd:\n" // alternate character that ends a single character or block of text
1303  "Variable:\n" // character that defines a variable (or parameter substitution)
1304  "StatementEnd: ;\n" // character that ends a statement
1305  "Escapement: \\\n" // character that performs 'escapement' like \n, etc.
1306  "IgnoreEscapement:\n" // quoted strings/chars that ignore 'escapement' (can have more than one)
1307  "DoubleQuotes:\n" // quoted string/chars that can have doubled quotes (list all chars like '"` for example)
1308  "LineContinuation: \\\n" // character that, at the end of the line, implies a line continuation
1309  "MacroDefinition: #define\n" // keyword for macro definition
1310  "Conditionals: #if #ifdef\n" // keywords that begin a conditional compile section, etc.
1311  "ElseCondition: #else\n" // keyword conditionals for 'else'
1312  "ElseIfCondition: #elif\n" // keyword conditionals for 'else if' (must be quoted if they contain white space)
1313  "EndIfCondition: #endif\n" // keyword that ends a conditional compile section, etc.
1314  "AlwaysTrue: \"#if 1\" \"#elif 1\" \"#if !0\" \"#elif !0\"\n"
1315  // conditionals that are always true (must be quoted if they contain white space)
1316 
1317  "AlwaysFalse: \"#if 0\" \"#elif 0\"\n"
1318  // conditionals that are alway false (must be quoted if they contain white space)
1319 
1320  "Keywords: if else for while do goto break switch case default char short long int unsigned const volatile "
1321  "float double struct class union enum typedef auto register inline "
1322  "namespace template using try catch except throw\n"
1323  // a comprehensive list of language keywords
1324 
1325  "AltKeywords: __attribute__ __inline __try __catch __except #pragma\n";
1326  // an 'alternate keyword' list
1327 
1328  return szC;
1329  }
1330  else if(nFileType == WBFILE_TYPE_JAVA ||
1331  nFileType == WBFILE_TYPE_JS)
1332  {
1333  static const char szJava[]=
1334  "Language: Java/JavaScript\n"
1335  "Comment: //\n"
1336  "CommentBlockBegin: /*\n"
1337  "CommentBlockEnd: */\n"
1338  "ScopeBegin: {\n"
1339  "ScopeEnd: }\n"
1340  "TextBegin: \"\n"
1341  "TextEnd: \"\n"
1342  "AltTextBegin:\n"
1343  "AltTextEnd:\n"
1344  "CharBegin: '\n"
1345  "CharEnd: '\n"
1346  "AltCharBegin:\n"
1347  "AltCharEnd:\n"
1348  "Variable:\n"
1349  "StatementEnd: ;\n"
1350  "Escapement: \\\n"
1351  "IgnoreEscapement:\n"
1352  "DoubleQuotes:\n"
1353  "LineContinuation: \\\n"
1354  "MacroDefinition:\n"
1355  "Conditionals:\n"
1356  "ElseCondition:\n"
1357  "ElseIfCondition:\n"
1358  "EndIfCondition:\n"
1359  "AlwaysTrue:\n"
1360  "AlwaysFalse:\n"
1361  "Keywords: if else elif for each in while do break switch case default char short long int final variant "
1362  "float double struct class union enum typedef try catch throw except "
1363  "finally namespace template using\n"
1364  "AltKeywords: __attribute__ __inline #pragma\n";
1365 
1366  return szJava;
1367  }
1368  else if(nFileType == WBFILE_TYPE_SHELL)
1369  {
1370  static const char szShell[]=
1371  "Language: Shell\n"
1372  "Comment: #\n"
1373  "CommentBlockBegin:\n"
1374  "CommentBlockEnd:\n"
1375  "ScopeBegin: {\n"
1376  "ScopeEnd: }\n"
1377  "TextBegin: \"\n"
1378  "TextEnd: \"\n"
1379  "AltTextBegin: `\n"
1380  "AltTextEnd: `\n"
1381  "CharBegin: '\n"
1382  "CharEnd: '\n"
1383  "AltCharBegin:\n"
1384  "AltCharEnd:\n"
1385  "StatementEnd:\n"
1386  "Escapement: \\\n"
1387  "IgnoreEscapement: '\n"
1388  "Variable: $\n"
1389  "DoubleQuotes:\n"
1390  "LineContinuation: \\\n"
1391  "MacroDefinition:\n"
1392  "Conditionals:\n"
1393  "ElseCondition:\n"
1394  "ElseIfCondition:\n"
1395  "EndIfCondition:\n"
1396  "AlwaysTrue:\n"
1397  "AlwaysFalse:\n"
1398  "Keywords: if fi else elif for in while do done break case local return exit echo\n"
1399  "AltKeywords:\n";
1400 
1401  return szShell;
1402  }
1403  else if(nFileType == WBFILE_TYPE_MAKEFILE ||
1404  nFileType == WBFILE_TYPE_AUTOCONF) // these too, for now - treat as Makefile for highlight
1405  {
1406  static const char szMakefile[]=
1407  "Language: Shell\n"
1408  "Comment: #\n"
1409  "CommentBlockBegin:\n"
1410  "CommentBlockEnd:\n"
1411  "ScopeBegin: {\n"
1412  "ScopeEnd: }\n"
1413  "TextBegin: \"\n"
1414  "TextEnd: \"\n"
1415  "AltTextBegin: `\n"
1416  "AltTextEnd: `\n"
1417  "CharBegin: '\n"
1418  "CharEnd: '\n"
1419  "AltCharBegin:\n"
1420  "AltCharEnd:\n"
1421  "StatementEnd:\n"
1422  "Escapement: \\\n"
1423  "IgnoreEscapement: '\n"
1424  "Variable: $\n"
1425  "DoubleQuotes:\n"
1426  "LineContinuation: \\\n"
1427  "MacroDefinition:\n"
1428  "Conditionals:\n"
1429  "ElseCondition:\n"
1430  "ElseIfCondition:\n"
1431  "EndIfCondition:\n"
1432  "AlwaysTrue:\n"
1433  "AlwaysFalse:\n"
1434  "Keywords: if fi else elif for in while do done break case local return exit echo\n"
1435  "AltKeywords: @if -if @for -for @while -while @echo -echo\n";
1436 
1437  return szMakefile;
1438  }
1439  else if(nFileType == WBFILE_TYPE_PERL)
1440  {
1441  // TODO: does Perl need syntax highlighting different from shell?
1442  }
1443  else if(nFileType == WBFILE_TYPE_PHP)
1444  {
1445  // TODO: does Perl need syntax highlighting different from shell/Perl?
1446  }
1447  else if(nFileType == WBFILE_TYPE_PYTHON)
1448  {
1449  // TODO: do python syntax highlighting
1450  }
1451  else if(nFileType == WBFILE_TYPE_HTML ||
1452  nFileType == WBFILE_TYPE_XML)
1453  {
1454  // TODO: does XML or HTML need some kind of syntax highlighting? it would have
1455  // to be different than the normal one...
1456  }
1457 
1458  return ""; // blank (for now, could do NULL instead but I prefer this)
1459 }
1460 
1461 
1462 
1463 
1465 // __ __ ____ _ _ _ _ //
1466 // | \/ | ___ _ __ _ _ / ___|__ _| | | |__ __ _ ___| | _____ //
1467 // | |\/| |/ _ \ '_ \| | | | | | / _` | | | '_ \ / _` |/ __| |/ / __| //
1468 // | | | | __/ | | | |_| | | |__| (_| | | | |_) | (_| | (__| <\__ \ //
1469 // |_| |_|\___|_| |_|\__,_| \____\__,_|_|_|_.__/ \__,_|\___|_|\_\___/ //
1470 // //
1472 
1473 static int ApplicationPreferences(XClientMessageEvent *pEvent)
1474 {
1475 XColor clr; // temporary
1476 
1477  if(!pMainFrame)
1478  {
1480  "Application Properties", "'Properties' and no container window");
1481  return 1;
1482  }
1483 
1484  clr.pixel = clrGreen.pixel; // temporary
1485 
1486  DLGColorDialog(pMainFrame->wID, NULL, &clr); // for now...
1487 
1488  return 1; // handled
1489 }
1490 
1491 
1492 static int FileExitHandler(XClientMessageEvent *pEvent)
1493 {
1494  // TODO: 'OnExit' processing for open files (files to be saved, etc.)
1495 
1496  bQuitFlag = 1; // time to die
1497 
1498  return 1; // handled
1499 }
1500 
1501 static int FileNewHandler(XClientMessageEvent *pEvent)
1502 {
1503 WBEditWindow *pEW;
1504 
1505  if(!pMainFrame)
1506  {
1508  "File New", "'File _New' and no container window");
1509  return 1;
1510  }
1511 
1512  // create a new child frame within the main frame
1513  // this should be pretty straightforward as I implement it properly
1514 
1515  // 1st, create a new 'WBEditWindow', attaching it to the frame
1516 
1517  pEW = WBCreateEditWindow(pMainFrame, NULL, szEditMenu, main_menu_handlers, 0);
1518 
1519  if(!pEW)
1520  {
1522  "File New", "'File _New' unable to create edit window");
1523  }
1524 
1525  return 1; // handled
1526 }
1527 
1528 
1529 static int FileOpenHandler(XClientMessageEvent *pEvent)
1530 {
1531  Window wIDOwner = pMainFrame ? pMainFrame->wID : None;
1532  WBEditWindow *pEW;
1533  char *pFile;
1534 
1535  pFile = DLGFileDialog(FileDialog_Open, wIDOwner, ".", "",
1536  ".txt\tText Files\n"
1537  ".c\tC language file\n"
1538  ".cpp\tC language file\n"
1539  ".h\tC language header\n"
1540  "Makefile\tMake Files\n"
1541  ".mk\tMake 'include' Files\n"
1542  ".am\tAutotools File\n"
1543  ".*\tAll Files\n");
1544 
1545  if(pFile)
1546  {
1547  DoFileOpen(pMainFrame, pFile);
1548 
1549  WBFree(pFile); // required resource cleanup
1550  }
1551 
1552  return 1; // handled
1553 }
1554 
1555 static int FileSaveHandler(XClientMessageEvent *pEvent)
1556 {
1557  Window wIDOwner = pMainFrame ? pMainFrame->wID : None;
1558 
1560  "File Save",
1561  "'File _Save' not currently implemented");
1562 
1563  return 1; // handled
1564 }
1565 
1566 static int FileSaveUIHandler(WBMenu *pMenu, WBMenuItem *pItem)
1567 {
1568  return -1; // disabled
1569 }
1570 
1571 static int FileSaveAsHandler(XClientMessageEvent *pEvent)
1572 {
1573  Window wIDOwner = pMainFrame ? pMainFrame->wID : None;
1574 
1576  "File Save As",
1577  "'File Save _As' not currently implemented");
1578 
1579  return 1; // handled
1580 }
1581 
1582 static int FileSaveAsUIHandler(WBMenu *pMenu, WBMenuItem *pItem)
1583 {
1584  return -1; // disabled
1585 }
1586 
1587 static int FileSaveAllHandler(XClientMessageEvent *pEvent)
1588 {
1589  Window wIDOwner = pMainFrame ? pMainFrame->wID : -1;
1590 
1592  "File Save All",
1593  "'File Save A_ll' not currently implemented");
1594 
1595  return 1; // handled
1596 }
1597 
1598 static int FileSaveAllUIHandler(WBMenu *pMenu, WBMenuItem *pItem)
1599 {
1600  return -1; // disabled
1601 }
1602 
1603 static int HelpAboutHandler(XClientMessageEvent *pEvent)
1604 {
1605  Window wIDOwner = pMainFrame ? pMainFrame->wID : None;
1606 
1607 
1608  DLGMessageBox(MessageBox_OK | /*MessageBox_Info*/ MessageBox_App, wIDOwner,
1609  "About X11workbench",
1610  "X11workbench - BBB's answer to a proper development environment for X11");
1611 
1612  return 1; // handled
1613 }
1614 
1615 static int FileCloseHandler(XClientMessageEvent *pEvent)
1616 {
1617  WBChildFrame *pC;
1618 
1619  if(!pMainFrame)
1620  {
1621  return 0;
1622  }
1623 
1624  pC = FWGetFocusWindow(pMainFrame);
1625 
1626  if(pC)
1627  {
1628  // TODO: check for 'safe to close it' ?
1629 
1630  FWRemoveContainedWindow(pMainFrame, pC);
1631 
1632  FWDestroyChildFrame(pC); // this will destroy the super-class as well
1633  }
1634 
1635  return 1;
1636 }
1637 
1638 static int TabLeftHandler(XClientMessageEvent *pEvent)
1639 {
1640 int iIndex;
1641 
1642  if(!pMainFrame)
1643  {
1644  return 0;
1645  }
1646 
1647  iIndex = FWGetChildFrameIndex(pMainFrame, NULL);
1648 
1649  WB_ERROR_PRINT("TEMPORARY: %s - move left %d\n", __FUNCTION__, iIndex);
1650 
1651  if(iIndex > 0)
1652  {
1653  FWSetFocusWindowIndex(pMainFrame, iIndex - 1);
1654  }
1655 
1656  return 1;
1657 }
1658 
1659 static int TabRightHandler(XClientMessageEvent *pEvent)
1660 {
1661 int iIndex;
1662 
1663  if(!pMainFrame)
1664  {
1665  return 0;
1666  }
1667 
1668  iIndex = FWGetChildFrameIndex(pMainFrame, NULL);
1669 
1670  WB_ERROR_PRINT("TEMPORARY: %s - move right %d\n", __FUNCTION__, iIndex);
1671 
1672  if(iIndex >= 0)
1673  {
1674  FWSetFocusWindowIndex(pMainFrame, iIndex + 1);
1675  }
1676 
1677  return 1;
1678 }
1679 
1680 static int TabMoveLeftHandler(XClientMessageEvent *pEvent)
1681 {
1682  WBChildFrame *pC;
1683 
1684  if(!pMainFrame)
1685  {
1686  return 0;
1687  }
1688 
1689  pC = FWGetFocusWindow(pMainFrame);
1690 
1691  if(pC)
1692  {
1694  }
1695 
1696  return 1;
1697 }
1698 
1699 static int TabMoveRightHandler(XClientMessageEvent *pEvent)
1700 {
1701  WBChildFrame *pC;
1702 
1703  if(!pMainFrame)
1704  {
1705  return 0;
1706  }
1707 
1708  pC = FWGetFocusWindow(pMainFrame);
1709 
1710  if(pC)
1711  {
1713  }
1714 
1715  return 1;
1716 }
1717 
1718 static int TabUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem)
1719 {
1720  if(FWGetNumContWindows(pMainFrame) > 1)
1721  {
1722  return 1; // enabled (more than one tab)
1723  }
1724 
1725  return -1; // disabled (zero or one child frames)
1726 }
1727 
1728 static int ToolBoxHandler(XClientMessageEvent *pEvent)
1729 {
1730  DLGMessageBox(MessageBox_WTF | MessageBox_No, None, "X11workbench - Unimplemented",
1731  "ToolBox Handler not (yet) implemented");
1732 
1733  return 1; // "handled"
1734 }
1735 
1736 static int ToolBoxUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem)
1737 {
1738  return 1; // enabled (TODO: check # of tabs, etc.)
1739 }
1740 
1741 
1742 
1743 static int HelpContentsHandler(XClientMessageEvent *pEvent)
1744 {
1745  Window wIDOwner = pMainFrame ? pMainFrame->wID : None;
1746 
1747  char *pTemp = DLGInputBox(wIDOwner, "Help Contents", "Enter a search term for the documentation", "WBInit", -1, -1);
1748 
1749  if(pTemp)
1750  {
1751  DoContextSensitiveHelp(pTemp);
1752 
1753  WBFree(pTemp);
1754  }
1755 // else
1756 // {
1757 // DLGMessageBox(MessageBox_OK | MessageBox_Bang, wIDOwner,
1758 // "Something Bad Happened", "Unexpected 'NULL' return from DLGInputBox");
1759 // }
1760 
1761  return 1; // handled
1762 }
1763 
1764 static int HelpContextHandler(XClientMessageEvent *pEvent)
1765 {
1766  Window wIDOwner = pMainFrame ? pMainFrame->wID : None;
1767 
1769  "Context Help", "TODO: implement the context-sensitive help");
1770 
1771 // DoContextSensitiveHelp(szWhateverWord);
1772 
1773  return 1; // handled
1774 }
1775 
1776 
1777 
1778 
1780 // SIGNAL HANDLER //
1782 
1783 
1784 typedef struct _xsiginfo_
1785 {
1786  const char *szSignal;
1787  int nSignal;
1788 } XSIGINFO;
1789 
1790 #define SIGINFO_ENTRY(X) { #X, X }
1791 static const XSIGINFO aSigInfo[] =
1792 {
1793 SIGINFO_ENTRY(SIGHUP), // terminate process terminal line hangup
1794 SIGINFO_ENTRY(SIGINT), // terminate process interrupt program
1795 SIGINFO_ENTRY(SIGQUIT), // create core image quit program
1796 SIGINFO_ENTRY(SIGILL), // create core image illegal instruction
1797 SIGINFO_ENTRY(SIGTRAP), // create core image trace trap
1798 SIGINFO_ENTRY(SIGABRT), // create core image abort(3) call (formerly SIGIOT)
1799 #ifdef SIGEMT
1800 SIGINFO_ENTRY(SIGEMT), // create core image emulate instruction executed
1801 #endif // SIGEMT
1802 SIGINFO_ENTRY(SIGFPE), // create core image floating-point exception
1804 SIGINFO_ENTRY(SIGBUS), // create core image bus error
1805 SIGINFO_ENTRY(SIGSEGV), // create core image segmentation violation
1806 SIGINFO_ENTRY(SIGSYS), // create core image non-existent system call invoked
1807 SIGINFO_ENTRY(SIGPIPE), // terminate process write on a pipe with no reader
1808 SIGINFO_ENTRY(SIGALRM), // terminate process real-time timer expired
1809 SIGINFO_ENTRY(SIGTERM), // terminate process software termination signal
1810 SIGINFO_ENTRY(SIGURG), // discard signal urgent condition present on socket
1812 //SIGINFO_ENTRY(SIGTSTP), // stop process stop signal generated from keyboard
1813 //SIGINFO_ENTRY(SIGCONT), // discard signal continue after stop
1814 SIGINFO_ENTRY(SIGCHLD), // discard signal child status has changed
1815 SIGINFO_ENTRY(SIGTTIN), // stop process background read attempted from control terminal
1816 SIGINFO_ENTRY(SIGTTOU), // stop process background write attempted to control terminal
1817 SIGINFO_ENTRY(SIGIO), // discard signal I/O is possible on a descriptor (see fcntl(2))
1818 SIGINFO_ENTRY(SIGXCPU), // terminate process cpu time limit exceeded (see setrlimit(2))
1819 SIGINFO_ENTRY(SIGXFSZ), // terminate process file size limit exceeded (see setrlimit(2))
1820 SIGINFO_ENTRY(SIGVTALRM),// terminate process virtual time alarm (see setitimer(2))
1821 SIGINFO_ENTRY(SIGPROF), // terminate process profiling timer alarm (see setitimer(2))
1822 SIGINFO_ENTRY(SIGWINCH), // discard signal Window size change
1823 #ifdef SIGINFO
1824 SIGINFO_ENTRY(SIGINFO), // discard signal status request from keyboard
1825 #endif // SIGINFO
1826 SIGINFO_ENTRY(SIGUSR1), // terminate process User defined signal 1
1827 SIGINFO_ENTRY(SIGUSR2), // terminate process User defined signal 2
1828 {NULL, 0} // marks end of list
1829 };
1830 
1831 
1832 static void signalproc(int iSig)
1833 {
1834 static int bCtrlCFlag = 0; // when I hit ctrl+c multiple times, kill the app anyway in case of infinite loop or something
1835 
1836  int i1;
1837 
1838 #if 0 /* this is broken now that I have a worker thread - no longer compatible */
1839  if(iSig == SIGTSTP) // suspend - special 'way cool' handling here [auto-fork!]
1840  {
1841 
1842  WB_DEBUG_PRINT(DebugLevel_Light | DebugSubSystem_Application,
1843  "\n**********************************************"
1844  "\nSignal received: SIGTSTP (detaching via fork)"
1845  "\n The process has now gone into the background"
1846  "\n and is still running (i.e. not suspended)."
1847  "\n**********************************************\n");
1848  fflush(stderr);
1849 
1850  // POSSIBLE (ALTERNATE) NON-FORKING METHOD
1851  // see man termios(4) - change process group of terminal, force me into the background
1852  // I change the controlling terminal process group to that of the shell that created me
1853 // {
1854 // pid_t idgParent;
1855 // int idParent;
1856 // idParent = getppid(); // parent PID
1857 // idgParent = getpgid(idParent); // get process group ID using parent's process id
1858 //
1859 // if(idgParent != -1) // wasn't an error
1860 // tcsetpgrp(0, idgParent);
1861 //
1862 // if(idParent != -1)
1863 // kill(idParent, SIGCHLD); // child process status changed
1864 // }
1865 
1866  // to simplify matters, I simply fork the process and exit from the original.
1867  // This satisfies the shell's need to wait for the original process ID when it's
1868  // not in the background, and effectively keeps the process running on the GUI.
1869  //
1870  // De nada. Bitte. You're welcome.
1871 
1872  if(fork()) // non-zero means fork failed or NOT the forked process
1873  {
1874  exit(0);
1875  }
1876  return;
1877  }
1878  else if(iSig == SIGCONT) // continue
1879  {
1880  return; // for now, just do nothing
1881  }
1882 #endif // 0
1883 
1884  for(i1=0; i1 < sizeof(aSigInfo)/sizeof(aSigInfo[0]); i1++)
1885  {
1886  if(!aSigInfo[i1].szSignal)
1887  {
1888  break;
1889  }
1890 
1891  if(aSigInfo[i1].nSignal == iSig)
1892  {
1893  WB_DEBUG_PRINT(DebugLevel_ERROR | DebugSubSystem_Application,
1894  "\nX11workbench - Signal received: %s\n", aSigInfo[i1].szSignal);
1895 
1896  // only some signals will actually terminate the application. I shall look for those now.
1897 
1898  if(iSig == SIGHUP || iSig == SIGINT || iSig == SIGQUIT ||
1899  iSig == SIGILL || iSig == SIGTRAP || iSig == SIGABRT ||
1900 #ifdef SIGEMT
1901  iSig == SIGEMT ||
1902 #endif // SIGEMT
1903  iSig == SIGSYS || iSig == SIGTERM || iSig == SIGSTOP ||
1904  iSig == SIGXCPU || iSig == SIGXFSZ || iSig == SIGFPE)
1905  {
1906  if(bQuitFlag && (iSig == SIGSTOP || iSig == SIGTERM || iSig == SIGINT))
1907  {
1908  // this section allows you to use TERM STOP or INT 3 times in a row to guarantee
1909  // that it will kill the process
1910  if(!bCtrlCFlag)
1911  {
1912  WB_ERROR_PRINT("\n----------------------------------------------------------------------------"
1913  "\n X11workbench CTRL+C signal handler"
1914  "\nINT/STOP/TERM, waiting for soft termination - signal again to terminate NOW!"
1915  "\n----------------------------------------------------------------------------\n");
1916  fflush(stderr); // make sure it flushes output IMMEDIATELY
1917  bCtrlCFlag = 1; // if I get another, I kill it
1918  }
1919  else
1920  {
1921  WB_ERROR_PRINT("\n----------------------------------------------------------------------------"
1922  "\n X11workbench CTRL+C signal handler"
1923  "\nINT/STOP/TERM, aborting waiting for soft termination - terminate RIGHT NOW!!"
1924  "\n----------------------------------------------------------------------------\n");
1925  exit(1); // exit with abnormal termination
1926  }
1927  }
1928  else
1929  {
1930  bCtrlCFlag = 0; // reset it (quit was aborted??)
1931  }
1932 
1933  bQuitFlag = TRUE; // soft termination
1934  }
1935 
1936  if(iSig == SIGKILL || iSig == SIGSEGV) // special handling, must terminate process
1937  {
1938  WB_ERROR_PRINT("caught signal %d, terminating now\n", iSig);
1939 
1940  exit(0);
1941  }
1942 
1943  if(iSig == SIGBUS) // might happen
1944  {
1945  WB_DEBUG_PRINT(DebugLevel_ERROR | DebugSubSystem_Application,
1946  "SIGBUS received (this is usually caused by use of a data pointer instead of a function pointer)\n");
1947  exit(1);
1948  }
1949 
1950  return;
1951  }
1952  }
1953 
1954  WB_DEBUG_PRINT(DebugLevel_Light | DebugSubSystem_Application,
1955  "signal proc (%d) (%08xH)\n", iSig, iSig);
1956 
1957 // bQuitFlag = TRUE;
1958 }
1959 
1960 
1961 static void SetSignalHandlers()
1962 {
1963  int i1;
1964  for(i1=0; i1 < sizeof(aSigInfo)/sizeof(aSigInfo[0]); i1++)
1965  {
1966  if(!aSigInfo[i1].szSignal)
1967  break;
1968 
1969  if(signal(aSigInfo[i1].nSignal, signalproc))
1970  {
1971  WB_WARN_PRINT("%s - WARNING: Unable to assign signal proc for %s\n", __FUNCTION__, aSigInfo[i1].szSignal);
1972  }
1973  }
1974 }
1975 
1976 
1977 
1978 
1979 
Icon - multiple question marks in red triangle.
void WBEndWaitCursor(Window wID)
decrement &#39;wait cursor&#39; count, restore to default when zero
GC WBBeginPaint(Window wID, XExposeEvent *pEvent, WB_GEOM *pgBounds)
&#39;Paint&#39; helper, creates a GC for use in updating the window in an Expose event handler ...
hard tabs - implied by &#39;FileType_MAKEFILE&#39;, otherwise explicit
Definition: text_object.h:119
structure for managing menu items
Definition: menu.h:185
#define FW_EDIT_SELECT_ALL_ACCEL
Definition: child_frame.h:132
int WBEditWindowLoadFile(WBEditWindow *pEditWindow, const char *pszFileName)
Open an existing file and read its contents into the Edit Window, storing the file name for later ref...
Definition: edit_window.c:454
&#39;window helper&#39; main header file for the X11workbench Toolkit API
#define FW_FILE_SAVE_ACCEL
Definition: child_frame.h:125
const TEXT_OBJECT_VTABLE * vtable
method function pointers (similar to C++ virtual member functions)
Definition: text_object.h:951
void FWRemoveContainedWindow(WBFrameWindow *pFW, WBChildFrame *pCont)
Removes a &#39;contained&#39; window from a frame window. Does not destroy the &#39;contained&#39; window...
int bQuitFlag
&#39;Quit&#39; Flag - you should check this periodically in your main (message) loop and exit whenever it is ...
#define WB_DEBUG_PRINT(L,...)
Preferred method of implementing conditional debug output.
Definition: debug_helper.h:299
static __inline__ Colormap WBDefaultColormap(Display *pDisplay)
returns the default colormap for the default screen of the specified display
#define FW_EDIT_UNDO_ACCEL
Definition: child_frame.h:134
set this flag for application top-level window and whenever it is destroyed the application will exit...
Definition: frame_window.h:298
Utilities for copying and drawing text, determining text extents, and so on.
Make Files with special handling (implies &#39;hard tab&#39;, always)
Definition: text_object.h:110
#define FWGetFocusWindow(pFW)
A macro to aid code readability, returning the Window ID of the contained window that has the focus...
Definition: frame_window.h:942
Window wID
Window id for the frame window.
Definition: frame_window.h:277
void WBExit()
deletes any remaining global objects, frees the Display pointer, and terminates event processing ...
#define FW_FILE_NEW_MENU
Definition: child_frame.h:105
void WBWaitForEvent(Display *pDisplay)
Wait for an event, blocking indefinitely.
Display * WBInit(const char *szDisplayName)
initializes default objects for the specified Display (required)
int WBCheckGetEvent(Display *pDisplay, XEvent *pEvent)
Main message loop, high level API to check for and retrieve the next event.
void PXM_RegisterAppIcons(char *ppRegAppLarge[], char *ppRegAppSmall[])
Icon Registration for application &#39;large&#39; and &#39;small&#39; icons.
int FWGetChildFrameIndex(WBFrameWindow *pFW, WBChildFrame *pCont)
Sets the focus to a specific contained window using its tab order index.
#define FW_EDIT_DELETE_MENU
Definition: child_frame.h:115
Edit Window API functions.
int DLGColorDialog(Window wIDOwner, XStandardColormap *pColorMap, XColor *pColor)
Display a modal Color Dialog window, returning the selected color in the XColor structure pointed to ...
Definition: dialog_impl.c:1805
#define FW_EDIT_REDO_ACCEL
Definition: child_frame.h:135
char * DLGInputBox(Window wIDOwner, const char *szTitle, const char *szPrompt, const char *szDefault, int iWidth, int iMaxChar)
Displays a special purpose dialog window that retrieves a character string as input.
Definition: dialog_impl.c:558
#define FW_FILE_SAVE_ALL_MENU
Definition: child_frame.h:110
#define FW_EDIT_SELECT_NONE_MENU
Definition: child_frame.h:117
Structure that defines a Child Frame within a Frame Window.
Definition: frame_window.h:426
default for OS
Definition: text_object.h:133
structure for managing menu items
Definition: menu.h:127
#define FW_FILE_SAVE_MENU
Definition: child_frame.h:108
Button Bits - No button.
void FWSetMenuHandlers(WBFrameWindow *pFW, const WBFWMenuHandler *pHandlerArray)
Function to assign the default menu handler to a frame window.
Definition: frame_window.c:794
Button Bits - OK button.
&#39;configuration helper&#39; main header file for the X11 Work Bench Toolkit API
set this to make window immediately visible
Definition: frame_window.h:299
#define FW_EDIT_CUT_ACCEL
Definition: child_frame.h:129
#define FW_EDIT_PROPERTIES_ACCEL
Definition: child_frame.h:136
#define MOVE_CHILD_FRAME_TAB_INDEX_LEFT
pass as &#39;iIndex&#39; for FWMoveChildFrameTabIndex() to move the tab index left
POSIX newline 0AH.
Definition: text_object.h:134
Icon - red stop sign.
Atom aMENU_COMMAND
commands sent by menus via ClientMessage
Icon - white &#39;middle finger&#39; on red triangle.
TEXT_OBJECT xTextObject
the &#39;TEXT_OBJECT&#39; member, that does MOST of the work
Definition: edit_window.h:174
#define FW_EDIT_PASTE_ACCEL
Definition: child_frame.h:131
void WBClearWindow(Window wID, GC gc)
&#39;Paint&#39; helper, erases background by painting the background color within the clipping region ...
void WBToolkitUsage(void)
Displays &#39;usage&#39; for toolkit options to stderr.
unsigned long WBGetWindowFGColor(Window wID)
Returns the currently assigned foreground color.
XML data (includes HTML)
Definition: text_object.h:109
void FWSetFocusWindowIndex(WBFrameWindow *pFW, int iIndex)
Sets the focus to a specific contained window using its tab order index.
int FWGetNumContWindows(const WBFrameWindow *pFW)
Returns the total number of &#39;contained&#39; windows.
void CHDumpConfig()
dump config information using debug output functions
Definition: conf_help.c:3226
void DLGSplashScreen(char *aXPM[], const char *szCopyright, unsigned long clrText)
Display a splash screen for 5 seconds (with animation and copyright string), and then return...
Definition: dialog_impl.c:1969
#define FW_EDIT_CUT_MENU
Definition: child_frame.h:112
#define FW_MENU_HANDLER_BEGIN(X)
Use this macro to begin definition of a WBFWMenuHandler array.
Definition: frame_window.h:893
#define WB_ERROR_PRINT(...)
Preferred method of implementing an &#39;error level&#39; debug message for all subsystems.
Definition: debug_helper.h:356
void WBFree(void *pBuf)
High performance memory sub-allocator &#39;free&#39;.
void WBDestroyWindow(Window wID)
Destroy a window.
program source
Definition: text_object.h:107
no special handling, no source decorations
Definition: text_object.h:106
void WBDelay(uint32_t uiDelay)
Delay for a specified period in microseconds.
void FWSetChildFrameDisplayName(WBChildFrame *pChildFrame, const char *szDisplayName)
Assign the display name.
Definition: child_frame.c:563
#define FW_MENU_HANDLER_END
Use this macro to complete the definition of a WBFWMenuHandler array.
Definition: frame_window.h:907
#define FW_EDIT_PROPERTIES_MENU
Definition: child_frame.h:120
int WBParseStandardArguments(int *pargc, char ***pargv, char ***penvp)
parses standard C arguments as passed to &#39;main()&#39;
#define FW_FILE_SAVE_ALL_ACCEL
Definition: child_frame.h:127
void FWDestroyChildFrame(WBChildFrame *pChildFrame)
Destroy an Child Frame.
Definition: child_frame.c:321
#define FW_FILE_SAVE_AS_MENU
Definition: child_frame.h:109
void WBDispatch(XEvent *pEvent)
Generic Event Dispatcher, using message type to dispatch.
void WBInitSizeHints(XSizeHints *pSH, Display *pDisplay, int iMinHeight, int iMinWidth)
initializes the XSizeHints structure with standard attributes
void(* set_filetype)(struct _text_object_ *pThis, int iLineFeed)
Set the current file type for the object.
Definition: text_object.h:404
XFontStruct * WBGetDefaultFont(void)
Returns a pointer to the default font&#39;s XFontStruct.
Atom aQUERY_CLOSE
query if it&#39;s ok to close (and optionally destroy yourself if ok) a window
Window wID
window identifier for the &#39;Child Frame&#39; window. may contain &#39;None&#39; while being destroyed ...
Definition: frame_window.h:429
CRLF 0DH,0AH.
Definition: text_object.h:136
#define FW_FILE_SAVE_AS_ACCEL
Definition: child_frame.h:126
WBEditWindow * WBCreateEditWindow(WBFrameWindow *pOwner, XFontStruct *pFont, const char *szFocusMenu, const WBFWMenuHandler *pHandlerArray, int fFlags)
Create an Edit Window.
Definition: edit_window.c:268
WBChildFrame childframe
elements common to a &#39;child frame&#39; (derived object)
Definition: edit_window.h:160
Type Flag - File Open Dialog.
void WBBeginWaitCursor(Window wID)
increment &#39;wait cursor&#39; count, set cursor to WB_WAIT_CURSOR
#define FW_EDIT_SELECT_ALL_MENU
Definition: child_frame.h:116
#define FW_EDIT_SELECT_NONE_ACCEL
Definition: child_frame.h:133
main controlling structure for frame windows
Definition: frame_window.h:274
#define FW_FILE_CLOSE_MENU
Definition: child_frame.h:106
Icon - application icon (from icon_app.xpm)
#define FW_FILE_OPEN_ACCEL
Definition: child_frame.h:124
Icon - exclamation point on yellow triangle.
#define FW_EDIT_REDO_MENU
Definition: child_frame.h:119
char * DLGFileDialog(int iType, Window wIDOwner, const char *szDefPath, const char *szDefName, const char *szExtAndDescList)
Display a modal File Dialog window, returning a WBAlloc&#39;d pointer to a null-byte terminated string co...
Definition: dialog_impl.c:964
#define FW_EDIT_COPY_ACCEL
Definition: child_frame.h:130
char * WBCopyString(const char *pSrc)
A simple utility that returns a WBAlloc() copy of a 0-byte terminated string.
void(* set_linefeed)(struct _text_object_ *pThis, int iLineFeed)
Set the current linefeed type for the object.
Definition: text_object.h:421
Structure that defines an Edit Window.
Definition: edit_window.h:158
WBFrameWindow * FWCreateFrameWindow(const char *szTitle, int idIcon, const char *szMenuResource, int iX, int iY, int iWidth, int iHeight, WBWinEvent pUserCallback, int iFlags)
Create a frame window.
Definition: frame_window.c:477
set this to enable a &#39;status bar&#39; at the bottom
Definition: frame_window.h:301
XFontStruct * WBGetWindowFontStruct(Window wID)
Returns the current XFontStruct pointer assigned to the window (may be NULL)
#define FW_EDIT_PASTE_MENU
Definition: child_frame.h:114
void(* set_tab)(struct _text_object_ *pThis, int iTab)
Set the current tab type for the object.
Definition: text_object.h:472
Frame Window API functions and definitions.
#define MOVE_CHILD_FRAME_TAB_INDEX_RIGHT
pass as &#39;iIndex&#39; for FWMoveChildFrameTabIndex() to move the tab index right
internal wrapper struct for X11 &#39;geometry&#39; definition
int WBCPUCount(void)
Get the number of available CPU cores.
void FWMoveChildFrameTabIndex(WBFrameWindow *pFW, WBChildFrame *pCont, int iIndex)
Sets the specific contained window to a particular index in the tab order.
#define FW_MENU_HANDLER_ENTRY(X, Y, Z)
Use this macro to define an entry for a WBFWMenuHandler array.
Definition: frame_window.h:902
void WBEndPaint(Window wID, GC gc)
&#39;Paint&#39; helper, frees resources and marks the update region &#39;valid&#39;
#define WB_WARN_PRINT(...)
Preferred method of implementing a &#39;warning level&#39; debug message for all subsystems.
Definition: debug_helper.h:349
Icon - yellow circle with white exclamation point.
#define FW_FILE_OPEN_MENU
Definition: child_frame.h:107
int DLGMessageBox(int iType, Window wIDOwner, const char *szTitle, const char *szMessage)
Display a modal &#39;message box&#39; dialog window with a specific title, message, and button combination...
Definition: dialog_impl.c:231
#define FW_EDIT_UNDO_MENU
Definition: child_frame.h:118
#define FW_FILE_NEW_ACCEL
Definition: child_frame.h:122
#define FW_EDIT_COPY_MENU
Definition: child_frame.h:113
void WBCatString(char **ppDest, const char *pSrc)
A simple utility that concatenates a string onto the end of a 0-byte terminated WBAlloc() string...