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