X11workbench Toolkit  1.0
edit_window.c
1 // _ _ _ _ _ //
3 // ___ __| |(_)| |_ __ __(_) _ __ __| | ___ __ __ ___ //
4 // / _ \ / _` || || __| \ \ /\ / /| || '_ \ / _` | / _ \\ \ /\ / / / __| //
5 // | __/| (_| || || |_ \ V V / | || | | || (_| || (_) |\ V V /_| (__ //
6 // \___| \__,_||_| \__|_____\_/\_/ |_||_| |_| \__,_| \___/ \_/\_/(_)\___| //
7 // |_____| //
8 // //
9 // a window into which you can type (and edit) text //
10 // //
12 
13 /*****************************************************************************
14 
15  X11workbench - X11 programmer's 'work bench' application and toolkit
16  Copyright (c) 2010-2019 by Bob Frazier (aka 'Big Bad Bombastic Bob')
17 
18 
19  DISCLAIMER: The X11workbench application and toolkit software are supplied
20  'as-is', with no warranties, either implied or explicit.
21  Any claims to alleged functionality or features should be
22  considered 'preliminary', and might not function as advertised.
23 
24  MIT-like license:
25 
26  There is no restriction as to what you can do with this software, so long
27  as you include the above copyright notice and DISCLAIMER for any distributed
28  work that is equal to or derived from this one, along with this paragraph
29  that explains the terms of the license if the source is also being made
30  available. A "derived work" describes a work that uses a significant portion
31  of the source files or algorithms that are included with this one.
32  Specifically excluded from this are files that were generated by the software,
33  or anything that is included with the software that is part of another package
34  (such as files that were created or added during the 'configure' process).
35  Specifically included is the use of part or all of any of the X11 workbench
36  toolkit source or header files in your distributed application. If you do not
37  ship the source, the above copyright statement is still required to be placed
38  in a reasonably prominent place, such as documentation, splash screens, and/or
39  'about the application' dialog boxes.
40 
41  Use and distribution are in accordance with GPL, LGPL, and/or the above
42  MIT-like license. See COPYING and README files for more information.
43 
44 
45  Additional information at http://sourceforge.net/projects/X11workbench
46 
47 ******************************************************************************/
48 
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <unistd.h>
52 #include <memory.h>
53 #include <string.h>
54 #include <strings.h>
55 
56 #define _EDIT_WINDOW_C_IMPLEMENTED_
57 
58 #include "window_helper.h"
59 #include "edit_window.h"
60 #include "conf_help.h"
61 #include "file_help.h"
62 #include "draw_text.h"
63 
64 #include "dialog_window.h" // for message boxen
65 #include "dialog_controls.h" // for 'aDIALOG_INIT'
66 
67 
68 #if 0 // assign to 0 to disable this trace-style debugging ALL of the time
69 #define CALLBACK_TRACKER WBDebugPrint("TEMPORARY - edit_window.c: %s - callback tracker\n", __FUNCTION__);
70 #else //
71 #define CALLBACK_TRACKER WB_DEBUG_PRINT((DebugLevel_Heavy | DebugSubSystem_EditWindow), "edit_window.c: %s - callback tracker\n", __FUNCTION__);
72 #endif // 0,1
73 
74 #define EDIT_WINDOW_LINE_SPACING 4 /* 4 spaces between each line */
75 
76 #define CALLBACK_CHECK_NULL(X) if(X) (X)
77 #define CALLBACK_CHECK_NULL2(X) (X) ? (X)
78 
79 
80 struct _PROPERTY_DLG_
81 {
82  WBEditWindow *pEditWindow;
83 };
84 
85 
86 
87 
88 int FWEditWindowEvent(Window wID, XEvent *pEvent);
89 static void InternalEditWindowDestructor(WBChildFrame *pC);
90 static void InternalEditWindowDestroy(WBEditWindow *pEditWindow);
91 
92 // UI callbacks for WBChildFrameUI
93 
94 static void internal_do_char(WBChildFrame *, XClientMessageEvent *); // handler for regular WB_CHAR Client Messages (WBChildFrame *, typed-in characters)
95 static void internal_scancode(WBChildFrame *, XClientMessageEvent *); // handler for 'other scan code' WB_CHAR Client Messages (WBChildFrame *, typed-in characters)
96 static void internal_bkspace(WBChildFrame *, int iACS); // 'backspace' delete character (WBChildFrame *, backspace equivalent). 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
97 static void internal_del(WBChildFrame *, int iACS); // 'delete' char under cursor (WBChildFrame *, delete equivalent). 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
98 static void internal_tab(WBChildFrame *, int iACS); // 'tab' char, or tab navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
99 static void internal_enter(WBChildFrame *, int iACS); // 'enter' char, or 'enter' for navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
100 static void internal_properties(WBChildFrame *); // display the property sheet for the displayed document (optional)
101 static void internal_uparrow(WBChildFrame *, int iACS); // 'up' arrow navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
102 static void internal_downarrow(WBChildFrame *, int iACS); // 'down' arrow navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
103 static void internal_leftarrow(WBChildFrame *, int iACS); // 'left' arrow navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
104 static void internal_rightarrow(WBChildFrame *, int iACS); // 'right' arrow navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
105 static void internal_home(WBChildFrame *, int iACS); // 'home' arrow navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
106 static void internal_end(WBChildFrame *, int iACS); // 'end' arrow navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
107 static void internal_pgup(WBChildFrame *, int iACS); // 'page up' navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
108 static void internal_pgdown(WBChildFrame *, int iACS); // 'page down' navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
109 static void internal_pgleft(WBChildFrame *, int iACS); // 'page left' navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
110 static void internal_pgright(WBChildFrame *, int iACS); // 'page right' navigation. 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
111 static void internal_help(WBChildFrame *, int iACS); // 'help' context (WBChildFrame *, F1). 'iACS' is the Alt/Ctrl/Shift flags. \sa aWB_CHAR
112 static void internal_hover_notify(WBChildFrame *, int x, int y); // 'mouse hover' notification (WBChildFrame *, x and y are pixel coords with respect to upper left corner)
113 static void internal_hover_cancel(WBChildFrame *); // 'mouse hover' cancel notification (WBChildFrame *, cancel any 'hover' action)
114 static int internal_is_ins_mode(WBChildFrame *); // returns non-zero if in 'insert' mode, 0 for 'overwrite'
115 static void internal_toggle_ins_mode(WBChildFrame *); // toggles insert mode on/off (WBChildFrame *, press 'INS' key)
116 static void internal_copy_to_cb(WBChildFrame *); // copy selection to clipboard
117 static void internal_paste_from_cb(WBChildFrame *); // paste from clipboard
118 static void internal_cut_to_cb(WBChildFrame *); // delete selection, copying to clipboard first
119 static void internal_delete_sel(WBChildFrame *); // delete selection only
120 static void internal_select_all(WBChildFrame *); // select all
121 static void internal_select_none(WBChildFrame *); // select none
122 static void internal_save(WBChildFrame *, const char *szFileName); // save to specified file name (WBChildFrame *, NULL to keep same file name)
123 static WB_PCSTR internal_get_file_name(WBChildFrame *); // get (const) pointer to file name string
124 static void internal_mouse_click(WBChildFrame *, int iX, int iY,
125  int iButtonMask, int iACS); // 'mouse click' notification. \sa aWB_POINTER
126 static void internal_mouse_dblclick(WBChildFrame *, int iX, int iY,
127  int iButtonMask, int iACS); // 'mouse double click' notification. \sa aWB_POINTER
128 static void internal_mouse_drag(WBChildFrame *, int iX, int iY,
129  int iButtonMask, int iACS); // 'mouse drag' (begin) notification. \sa aWB_POINTER
130 static void internal_mouse_drop(WBChildFrame *, int iX, int iY,
131  int iButtonMask, int iACS); // 'mouse drop' (drag end) notification. \sa aWB_POINTER
132 static void internal_mouse_move(WBChildFrame *, int iX, int iY); // 'mouse motion' notification. \sa aWB_POINTER
133 static void internal_scroll_vert(WBChildFrame *, int iMode, int iValue); // 'scroll vertical' notification. \details A higher-level scrolling notification. 'iMode' is 0 for absolute, 1 for relative. 'iValue' is the absolute (or relative) new vertical scroll position to assign \sa aSCROLL_NOTIFY
134 static void internal_scroll_horiz(WBChildFrame *, int iMode, int iValue); // 'scroll vertical' notification. \details A higher-level scrolling notification. 'iMode' is 0 for absolute, 1 for relative. 'iValue' is the absolute (or relative) new horizontal scroll position to assign \sa aSCROLL_NOTIFY
135 
136 static void internal_mouse_cancel(WBChildFrame *); // 'mouse cancel' notification (cancel 'drag', etc.). \sa aWB_POINTER
137 static void internal_get_row_col(WBChildFrame *pC, int *piR, int *piC);// get row/col (etc.)
138 static int internal_has_selection(WBChildFrame *pC); // returns non-zero value if there is a selection
139 static void internal_undo(WBChildFrame *); // perform an undo
140 static void internal_redo(WBChildFrame *); // perform a re-do
141 static int internal_can_undo(WBChildFrame *); // returns non-zero value if 'can undo'
142 static int internal_can_redo(WBChildFrame *); // returns non-zero value if 'can redo'
143 static int internal_is_empty(WBChildFrame *); // returns non-zero value if 'empty'
144 
145 
146 static void internal_update_status_text(WBEditWindow *); // called whenever status text should change
147 static void internal_new_cursor_pos(WBEditWindow *); // called whenever cursor position changes.
148 
149 static int PropertyDialogCallback(Window wID, XEvent *pEvent);
150 
151 
152 
153 static XColor clrFG, clrBG, clrHFG, clrHBG;
154 static int iInitColorFlag = 0;
155 
156 
157 static WBChildFrameUI internal_CFUI =
158 {
160  internal_do_char, internal_scancode, internal_bkspace, internal_del,
161  internal_tab, internal_enter, internal_properties,
162  internal_uparrow, internal_downarrow,
163  internal_leftarrow, internal_rightarrow, internal_home, internal_end,
164  internal_pgup, internal_pgdown, internal_pgleft, internal_pgright,
165  internal_help, internal_hover_notify, internal_hover_cancel, internal_is_ins_mode,
166  internal_toggle_ins_mode, internal_copy_to_cb, internal_paste_from_cb, internal_cut_to_cb,
167  internal_delete_sel, internal_select_all, internal_select_none, internal_save,
168  internal_get_file_name, internal_mouse_click, internal_mouse_dblclick, internal_mouse_drag,
169  internal_mouse_drop, internal_mouse_move, internal_scroll_vert, internal_scroll_horiz,
170  internal_mouse_cancel, internal_get_row_col, internal_has_selection, internal_undo,
171  internal_redo, internal_can_undo, internal_can_redo, internal_is_empty
172 };
173 
174 
175 
193 
210 Atom aEW_EDIT_CHANGE=None;
211 
212 
213 
214 
215 //#define LOAD_COLOR0(X,Y) if(CHGetResourceString(WBGetDefaultDisplay(), X, Y, sizeof(Y)) > 0) { }
216 //#define LOAD_COLOR(X,Y,Z) if(CHGetResourceString(WBGetDefaultDisplay(), X, Y, sizeof(Y)) <= 0){ WB_WARN_PRINT("%s - WARNING: can't find color %s, using default value %s\n", __FUNCTION__, X, Z); strcpy(Y,Z); }
217 #define COPY_COLOR_NAME(X,Y,Z) {const char *pX = X(WBGetDefaultDisplay()); if(pX) strncpy(Y,pX,sizeof(Y)); else strncpy(Y,Z,sizeof(Y));}
218 
219 static void InternalCheckEWColorsAndAtoms(void)
220 {
221  Colormap colormap;
222 
223  // *Frame.background, *Frame.foreground, *WmFrame.background, *WmFrame.foreground,
224  // *Form.background, *Form.foreground, *background, *foreground
225 
226  if(aEW_EDIT_CHANGE == None)
227  {
228  aEW_EDIT_CHANGE = WBGetAtom(WBGetDefaultDisplay(), "EW_EDIT_CHANGE");
229  }
230 
231  if(aEW_HOVER_NOTIFY == None)
232  {
233  aEW_HOVER_NOTIFY = WBGetAtom(WBGetDefaultDisplay(), "EW_HOVER_NOTIFY");
234  }
235 
236  if(!iInitColorFlag)
237  {
238  char szFG[16], szBG[16], szHFG[16], szHBG[16]; // note colors can typically be up to 13 characters + 0 byte
239 
240  colormap = DefaultColormap(WBGetDefaultDisplay(), DefaultScreen(WBGetDefaultDisplay()));
241 
242  COPY_COLOR_NAME(CHGetTextColor,szFG,"#000000");
243  COPY_COLOR_NAME(CHGetBackgroundColor,szBG,"#ffffff");
244 
247 
248 #if 0
249  // (these color names and standards have changed *WAY* too many times...)
250  LOAD_COLOR0("*Text.foreground",szFG) else LOAD_COLOR0("*Edit.foreground", szFG)
251  else LOAD_COLOR("*foreground", szFG, "#000000");
252  LOAD_COLOR0("*Text.background",szBG) else LOAD_COLOR0("*Edit.background", szBG)
253  else LOAD_COLOR("*background", szBG, "white"); // pure white background by default
254 
255  LOAD_COLOR("selected_bg_color", szABG, "#0040FF"); // a slightly greenish blue for the 'selected' BG color
256  LOAD_COLOR("selected_fg_color", szAFG, "white"); // white FG when selected
257 
258  WB_ERROR_PRINT("TEMPORARY: %s - edit window colors: FG=%s BG=%s AFG=%s ABG=%s\n", __FUNCTION__,
259  szFG, szBG, szAFG, szABG);
260 #endif // 0
261 
262  XParseColor(WBGetDefaultDisplay(), colormap, szFG, &clrFG);
263  XAllocColor(WBGetDefaultDisplay(), colormap, &clrFG);
264  XParseColor(WBGetDefaultDisplay(), colormap, szBG, &clrBG);
265  XAllocColor(WBGetDefaultDisplay(), colormap, &clrBG);
266  XParseColor(WBGetDefaultDisplay(), colormap, szHFG, &clrHFG);
267  XAllocColor(WBGetDefaultDisplay(), colormap, &clrHFG);
268  XParseColor(WBGetDefaultDisplay(), colormap, szHBG, &clrHBG);
269  XAllocColor(WBGetDefaultDisplay(), colormap, &clrHBG);
270 
271  iInitColorFlag = 1;
272  }
273 }
274 
275 
277  const char *szFocusMenu, const WBFWMenuHandler *pHandlerArray,
278  int fFlags)
279 {
280 WBEditWindow *pRval;
281 Display *pDisplay;
282 int iRet;
283 
284 
285  CALLBACK_TRACKER;
286 
287  InternalCheckEWColorsAndAtoms();
288 
289  if(!pOwner)
290  {
291  return NULL;
292  }
293 
294  pDisplay = WBGetWindowDisplay(pOwner->wID);
295 
296  pRval = (WBEditWindow *)WBAlloc(sizeof(*pRval));
297 
298  if(!pRval)
299  {
300  WB_ERROR_PRINT("ERROR: %s - not enough memory\n", __FUNCTION__);
301  return NULL;
302  }
303 
304  bzero(pRval, sizeof(*pRval));
305 
306  pRval->ulTag = EDIT_WINDOW_TAG;
307  pRval->szFileName = NULL; // explicitly do this, though the bzero would've
308  pRval->pUserCallback = NULL; // explicitly do this, too
309 
312 
313 // pRval->xTextObject.vtable->set_col(&(pRval->xTextObject), 0);
314 // pRval->xTextObject.vtable->set_row(&(pRval->xTextObject), 0);
315 
316 
317  // create the actual window.
318 
319  iRet = FWInitChildFrame(&(pRval->childframe), pOwner, pFont, // NOTE: a copy of pFont will be in 'childframe.pFont'
320  szFocusMenu, pHandlerArray,
321  FWEditWindowEvent, fFlags);
322 
323  if(iRet < 0)
324  {
325  WB_ERROR_PRINT("ERROR: %s - unable to initialize child frame\n", __FUNCTION__);
326 
327  WBFree(pRval);
328 
329  return NULL;
330  }
331 
332 
333  pRval->xTextObject.wIDOwner = pRval->childframe.wID; // TODO: make assigning this an API function?
334 
335 
336  // assign my 'UI' vtable pointer, which will be (intelligently) called by the 'Child Frame' event handler
337  // this standardizes the various UI methods and makes coding a complex UI quite a bit easier
338  pRval->childframe.pUI = &internal_CFUI; // Child Frame UI function vtable
339 
340  // assign my 'destructor', which will be called by FWDestroyChildFrame
341  // THIS must be done LAST, since 'FWInitChildFrame' might call FWDestroyChildFrame on error
342  // and I don't want to call the 'destructor' yet.
343  pRval->childframe.destructor = InternalEditWindowDestructor;
344 
345 
346  // TODO: any other initialization belongs HERE. if error, call FWDestroyChildFrame() and return
347  // a NULL immediately (since that would destroy the child frame AND the Edit Window stuff)
348 
349 
350  internal_update_status_text(pRval); // update status text now.
351 
353  333333, 1, 1); // TODO: use #define for timer ID and period (1/3 second for now))
354  // NOTE: when I unregister the window callback, the timer will be deleted automatically
355 
356  return pRval;
357 }
358 
359 // this function destroys any allocated objects in the WBEditWindow, but doesn't free the pointer
360 static void InternalEditWindowDestroy(WBEditWindow *pEditWindow)
361 {
362  // these next 'things' are private to this particular 'class'
363 
364  if(pEditWindow->szFileName)
365  {
366  WBFree(pEditWindow->szFileName);
367  pEditWindow->szFileName = NULL;
368  }
369 
370  WBDestroyInPlaceTextObject(&(pEditWindow->xTextObject));
371 
372  pEditWindow->ulTag = 0; // not valid any more
373 }
374 
375 static void InternalEditWindowDestructor(WBChildFrame *pC)
376 {
377  WBEditWindow *pEW = (WBEditWindow *)pC;
378 
379 // WB_ERROR_PRINT("TEMPORARY: %s - destroying edit window %p\n", __FUNCTION__, pEW);
380 
381  InternalEditWindowDestroy(pEW);
382 
383  bzero(pEW, sizeof(*pEW)); // in case anything else 'stale' is there
384 
385  WBFree(pEW);
386 
387 // WB_ERROR_PRINT("TEMPORARY: %s - destroyed edit window %p\n", __FUNCTION__, pEW);
388 }
389 
391 {
392  if(!WBIsValidEditWindow(pEditWindow))
393  {
394  WB_ERROR_PRINT("ERROR: %s - invalid Edit Window pointer %p\n", __FUNCTION__, pEditWindow);
395  return;
396  }
397 
398  if(pEditWindow->pUserCallback)
399  {
400  // TODO: Send an aDESTROY_NOTIFY ClientMessage 'destroy' notification (once I document it)
401 
402  // TODO: send a 'DestroyNotify' event instead???
403 
404  pEditWindow->pUserCallback = NULL;
405  }
406 
407  if(pEditWindow->childframe.pUserCallback == FWEditWindowEvent)
408  {
409  pEditWindow->childframe.pUserCallback = NULL; // prevents any kind of recursion from messages (unlikely)
410  }
411 
412  if(pEditWindow->childframe.destructor == NULL)
413  {
414  WB_ERROR_PRINT("ERROR: %s - destructor is NULL - pointer will not be free'd\n", __FUNCTION__);
415 
416  InternalEditWindowDestroy(pEditWindow); // perform the necessary destruction *ANYWAY* but don't free the pointer
417 
418  // TODO: ALWAYS assign the destructor to NULL, and THEN call it directly after calling FWDestroyChildFrame() ?
419  }
420 
421  if(pEditWindow->childframe.wID != None)
422  {
424  pEditWindow->childframe.wID, 1); // the preferred method, when practical, is to delete it explicitly
425  }
426 
427  // the last step destroys the child frame, which will destroy the Edit Window as well
428 
429  FWDestroyChildFrame(&(pEditWindow->childframe)); // destroy window, free up all resources, call destructor (if not NULL)
430 }
431 
433 {
435 
436 
437  if(pRval && !WBIsValidEditWindow(pRval))
438  {
439  pRval = NULL;
440  }
441 
442  return pRval;
443 }
444 
445 
446 int WBEditWindowLoadFile(WBEditWindow *pEditWindow, const char *pszFileName)
447 {
448 char *pBuf = NULL;
449 long cbBuf = 0;
450 int iRval = -1;
451 
452 
453  CALLBACK_TRACKER;
454 
455  if(!pEditWindow || !WBIsValidEditWindow(pEditWindow)
456  || !pszFileName || !*pszFileName)
457  {
458  WBDebugPrint("TEMPORARY: bad parameters in %s\n", __FUNCTION__);
459  return -1;
460  }
461 
462  // implement 'load file'. handle unicode files. UTF-16 files begin with 0xff, 0xfe
463  // UTF-8 files are assumed to be the same as ASCII (with no prefix).
464 
465 
466  if(pEditWindow->szFileName)
467  {
468  WBFree(pEditWindow->szFileName);
469  }
470 
471 // pEditWindow->xTextObject.vtable->init(&(pEditWindow->xTextObject));
472  WBEditWindowClear(pEditWindow);
473 
474  pEditWindow->szFileName = WBCopyString(pszFileName);
475  pEditWindow->llModDateTime = WBGetFileModDateTime(pEditWindow->szFileName);
476 
477  // load the file into a buffer
478 
479  cbBuf = (long)WBReadFileIntoBuffer(pszFileName, &pBuf);
480 
481  if(cbBuf >= 0 && pBuf)
482  {
483  if(cbBuf >= 2 && (unsigned char)pBuf[0] == 0xff && (unsigned char)pBuf[1] == 0xfe)
484  {
485  // TODO: unicode file!
486 // pEditWindow->xTextObject.vtable->set_text(&(pEditWindow->xTextObject), pBuf + 2, cbBuf - 2);
487  }
488  else
489  {
490  // TODO: fix line endings first??
491  pEditWindow->xTextObject.vtable->set_row(&(pEditWindow->xTextObject),0);
492  pEditWindow->xTextObject.vtable->set_col(&(pEditWindow->xTextObject),0);
493 
494 // internal_new_cursor_pos(pE);
495  pEditWindow->xTextObject.vtable->set_text(&(pEditWindow->xTextObject), pBuf, cbBuf);
496 // pEditWindow->xTextObject.vtable->ins_chars(&(pEditWindow->xTextObject), pBuf, cbBuf);
497 
498  pEditWindow->xTextObject.vtable->set_row(&(pEditWindow->xTextObject),0);
499  pEditWindow->xTextObject.vtable->set_col(&(pEditWindow->xTextObject),0);
500  }
501 
502  iRval = 0; // for now; later, check for error state
503  }
504  else
505  {
506  iRval = -1;
507  }
508 
509  if(pBuf)
510  {
511  WBFree(pBuf);
512  }
513 
514  FWChildFrameRecalcLayout(&(pEditWindow->childframe));
515 
516  if(pEditWindow->pUserCallback)
517  {
518  XClientMessageEvent evt;
519 
520  bzero(&evt, sizeof(evt));
521 
522  evt.type=ClientMessage;
523  evt.display=WBGetWindowDisplay(pEditWindow->childframe.wID);
524  evt.window=pEditWindow->childframe.wID;
525  evt.message_type=aEW_EDIT_CHANGE;
526  evt.format=32;
527 
528  evt.data.l[0] = 0; // undo
529  evt.data.l[1] = 0; // cursor x,y
530  evt.data.l[2] = 0;
531 
532  pEditWindow->pUserCallback(pEditWindow->childframe.wID, (XEvent *)&evt);
533  }
534 
535  return iRval;
536 }
537 
538 int WBEditWindowSaveFile(WBEditWindow *pEditWindow, const char *pszFileName)
539 {
540  if(!pEditWindow || !WBIsValidEditWindow(pEditWindow))
541  {
542  return -1;
543  }
544 
545  if(!pszFileName || !*pszFileName)
546  {
547  pszFileName = pEditWindow->szFileName;
548  }
549 
550  if(!pszFileName || !*pszFileName)
551  {
552  return -1; // error (no file name)
553  }
554 
555  // TODO: implement 'file save'
556 
557  pEditWindow->llModDateTime = WBGetFileModDateTime(pEditWindow->szFileName);
558 
559 
560 
561  return -1; // error
562 }
563 
564 void WBEditWindowClear(WBEditWindow *pEditWindow)
565 {
566  if(!pEditWindow || !WBIsValidEditWindow(pEditWindow))
567  {
568  return;
569  }
570 
571  WBDestroyInPlaceTextObject(&(pEditWindow->xTextObject));
572  WBInitializeInPlaceTextObject(&(pEditWindow->xTextObject), pEditWindow->childframe.wID);
573  pEditWindow->xTextObject.vtable->set_linefeed(&(pEditWindow->xTextObject), LineFeed_DEFAULT);
574 
575  FWChildFrameRecalcLayout(&(pEditWindow->childframe));
576 }
577 
578 void WBEditWindowRegisterCallback(WBEditWindow *pEditWindow, WBWinEvent pUserCallback)
579 {
580  if(!pEditWindow || !WBIsValidEditWindow(pEditWindow))
581  {
582  return;
583  }
584 
585  pEditWindow->pUserCallback = pUserCallback;
586 }
587 
588 
589 
591 // //
592 // _____ _ _ _ _ _ //
593 // | ____|__ __ ___ _ __ | |_ | | | | __ _ _ __ __| || | ___ _ __ //
594 // | _| \ \ / // _ \| '_ \ | __| | |_| | / _` || '_ \ / _` || | / _ \| '__| //
595 // | |___ \ V /| __/| | | || |_ | _ || (_| || | | || (_| || || __/| | //
596 // |_____| \_/ \___||_| |_| \__| |_| |_| \__,_||_| |_| \__,_||_| \___||_| //
597 // //
598 // //
600 
601 
602 
603 int FWEditWindowEvent(Window wID, XEvent *pEvent)
604 {
605 WBEditWindow *pE;
606 WBGC gc;
607 WB_GEOM geom;//, geom2;
608 Display *pDisplay = WBGetWindowDisplay(wID);
609 
610 
611  pE = WBEditWindowFromWindowID(wID);
612  if(!pE)
613  {
614  return 0;
615  }
616 
617  switch(pEvent->type)
618  {
619  case Expose:
620 // WB_ERROR_PRINT("TEMPORARY: %s - expose event\n", __FUNCTION__);
621  geom.x = pEvent->xexpose.x;
622  geom.y = pEvent->xexpose.y;
623  geom.width = pEvent->xexpose.width;
624  geom.height = pEvent->xexpose.height;
625 
626  // TEMPORARY - just erase the background, for now...
627  gc = WBBeginPaintGeom(wID, &geom);
628 
629  WBSetBackground(gc, clrBG.pixel);
630 
631 // WBGetWindowGeom(wID, &geom2);
632 //
633 // // this is client geometry, not window geometry, so fix it
634 // geom2.x = 1; // 1-pixel border
635 // geom2.y = 1;
636 // geom2.width -= 2; // 1 pixel border on BOTH sides
637 // geom2.height -= 2;
638 //
639 // NOTE: for some reason this un-does what happens later in do_expose() ... maybe XSync after?
640 // WBSetForeground(gc, clrBG.pixel);
641 // WBFillRectangle(pDisplay, wID, gc, geom2.x, geom2.y, geom2.width, geom2.height);
642 
643  WBSetForeground(gc, clrFG.pixel);
644 
645  // TODO: 'split' handling - 2 different sections must be painted separately
646 
647  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->do_expose)(&(pE->xTextObject), pDisplay, wID, gc,
648  &geom, // the GEOM to 'paint to'
649  &(pE->childframe.geom),//NULL,//&geom2, // the GEOM bordering the window's viewport (NULL for ALL)
650  pE->childframe.pFont);
651  WBEndPaint(wID, gc);
652 
653  return 1; // "handled"
654 
655  case DestroyNotify:
656  // if I'm destroying ME, then I must free up the structure.
657  // if this callback is being called, assume NOT recursive.
658 
659  if(pEvent->xdestroywindow.window == wID)
660  {
661  pE->childframe.wID = None; // assign 'none' as the window ID, since I already destroyed it. don't re-destroy it.
662 
663  WBDestroyEditWindow(pE); // this should fix everything else.
664 
665  return 1; // handled
666  }
667 
668  break;
669 
670  case ClientMessage:
671  if(pEvent->xclient.message_type == aRESIZE_NOTIFY ||
672  pEvent->xclient.message_type == aRECALC_LAYOUT)
673  {
674  WB_RECT rctView;
675 
676  rctView.top = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_row)(&(pE->xTextObject)) : 0;
677  rctView.left = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_col)(&(pE->xTextObject)) : 0;
678 
679  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->get_view)(&(pE->xTextObject), &rctView);
680 
681  // TODO: process re-calculation of the extents, etc.
682 
684  rctView.top,
685  CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_rows)(&(pE->xTextObject)) : 0,
686  rctView.left,
687  CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_cols)(&(pE->xTextObject)) : 0,
691 // pE->childframe.pFont->ascent + pE->childframe.pFont->ascent + EDIT_WINDOW_LINE_SPACING,
692  }
693  else if(pEvent->xclient.message_type == aWB_TIMER)
694  {
695  static int iTimerThingy = 0;
696 
697  // only when this tab is visible do I call the callback.
698 
699  if(pE->childframe.pOwner && // just in case
700  FWGetChildFrameIndex(pE->childframe.pOwner, NULL) // focus window's tab index
701  == FWGetChildFrameIndex(pE->childframe.pOwner, &(pE->childframe))) // THIS window's tab index
702  {
703 // WB_ERROR_PRINT("TEMPORARY: %s - timer\n", __FUNCTION__);
704 
705  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_blink)(&(pE->xTextObject), 1);
706 
707  if(iTimerThingy >= 0)
708  {
709  iTimerThingy ++; // again, only when I have the focus do I do this
710  iTimerThingy &= 3;
711 
712  if(!iTimerThingy && pE->szFileName && pE->szFileName[0])
713  {
714  // see if the file was modified
715 
716  int iTemp = WBCheckFileModDateTime(pE->szFileName, pE->llModDateTime);
717 
718  if(iTemp != 0)
719  {
720  iTimerThingy = -1; // so I don't recursively do this
721 
722  if(iTemp > 0)
723  {
725  "File Modified", "This file has been modified on disk - reload?")
726  == IDYES)
727  {
728  // TODO: re-load the file
729 do_file_reload:
731  "File Modified", "file re-load not (yet) implemented");
732  }
733  }
734  else if(iTemp < 0)
735  {
737  "File Modified", "file mod date is OLDER than before - what happened?\n\nDo you want to reload it?")
738  == IDYES)
739  {
740  goto do_file_reload;
741  }
742  }
743 
744  pE->llModDateTime = WBGetFileModDateTime(pE->szFileName); // re-assign so I don't show 'mod' again
745 
746  iTimerThingy = 0; // so I don't eternally BLOCK this
747  }
748  }
749  }
750  }
751  }
752  else if(pEvent->xclient.message_type == aQUERY_CLOSE)
753  {
754  if(pE->pUserCallback)
755  {
756  int iRval = pE->pUserCallback(wID, pEvent); // allow the user callback to determine when to close
757 
758  if(iRval)
759  {
760  return iRval;
761  }
762  }
763 
764  return 0; // for now, just return 'ok to close' whether I've saved or not
765  }
766  }
767 
768  return 0; // "not handled"
769 }
770 
771 
772 
774 // //
775 // _ _ ___ ____ _ _ _ _ //
776 // | | | ||_ _| / ___| __ _ | || || |__ __ _ ___ | | __ //
777 // | | | | | | | | / _` || || || '_ \ / _` | / __|| |/ / //
778 // | |_| | | | | |___| (_| || || || |_) || (_| || (__ | < //
779 // \___/ |___| \____|\__,_||_||_||_.__/ \__,_| \___||_|\_\ //
780 // //
781 // //
783 
784 
785 static void internal_update_status_text(WBEditWindow *pE) // called whenever cursor position changes.
786 {
787 WBChildFrame *pC = &(pE->childframe);
788 int iR, iC;
789 char tbuf[1024];
790 
791  CALLBACK_TRACKER;
792 
793  if(!WBIsValidEditWindow(pE))
794  {
795  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
796 
797  return;
798  }
799 
800  internal_get_row_col(pC, &iR, &iC);
801 
802  if(pC->szStatusText)
803  {
804  WBFree(pC->szStatusText);
805  pC->szStatusText = NULL;
806  }
807 
808  snprintf(tbuf, sizeof(tbuf), "Row,Col: %d,%d\tlines: %d width: %d\t%s\t",
809  iR, iC,
810  CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_rows)(&(pE->xTextObject)) : 0,
811  CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_cols)(&(pE->xTextObject)) : 0,
812  (const char *)((CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_insmode)(&(pE->xTextObject)) : 0)
813  == InsertMode_INSERT ? "INS" :
814  (const char *)((CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_insmode)(&(pE->xTextObject)) : 0)
815  == InsertMode_OVERWRITE ? "OVR" : "???")));
816 
817  pC->szStatusText = WBCopyString(tbuf);
818 
819  if(!pC->szStatusText)
820  {
821  WB_ERROR_PRINT("ERROR: %s - not enough memory to display status\n", __FUNCTION__);
822  }
823 
825 }
826 
827 static void internal_new_cursor_pos(WBEditWindow *pE) // called whenever cursor position changes.
828 {
829  CALLBACK_TRACKER;
830 
831  if(WBIsValidEditWindow(pE))
832  {
833  internal_update_status_text(pE);
834 
835  // see if the row exceeds the viewport, and if that's the case, scroll it.
836 
837 
838 
839  // TODO: other things, like messing with the display area, re-calc layout, re-paint, etc.
840  // check to see if top/bottom rows changed, invalidate old line, validate new line, see if
841  // horizontal scrolling entire window or just the cursor, etc. etc. etc.
842  }
843 }
844 
845 static void internal_notify_change(WBChildFrame *pC, int bUndo)
846 {
847 WBEditWindow *pE = (WBEditWindow *)pC;
848 
849  if(!WBIsValidEditWindow(pE))
850  {
851  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
852 
853  return;
854  }
855 
856  if(pE->pUserCallback)
857  {
858  XClientMessageEvent evt;
859 
860  bzero(&evt, sizeof(evt));
861 
862  evt.type=ClientMessage;
863  evt.display=WBGetWindowDisplay(pC->wID);
864  evt.window=pC->wID;
865  evt.message_type=aEW_EDIT_CHANGE;
866  evt.format=32;
867 
868  evt.data.l[0] = bUndo;
869  evt.data.l[1] = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_row)(&(pE->xTextObject)) : 0;
870  evt.data.l[2] = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_col)(&(pE->xTextObject)) : 0;
871 
872  pE->pUserCallback(pC->wID, (XEvent *)&evt);
873  }
874 }
875 
876 static void internal_do_char(WBChildFrame *pC, XClientMessageEvent *pEvent)
877 {
878 WBEditWindow *pE = (WBEditWindow *)pC;
879 int iKey, iACS, nChar;
880 char *pBuf;
881 
882 
883  CALLBACK_TRACKER;
884 
885  if(!WBIsValidEditWindow(pE))
886  {
887  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
888 
889  return;
890  }
891 
892  // TODO: determine whether or not the character is printable
893 
894  iKey = pEvent->data.l[0]; // result from WBKeyEventProcessKey()
895  iACS = pEvent->data.l[1];
896  nChar = pEvent->data.l[2];
897  pBuf = (char *)&(pEvent->data.l[3]);
898 
899  if(iACS && (iACS & WB_KEYEVENT_ACSMASK) != WB_KEYEVENT_SHIFT) // only SHIFT can be used here
900  {
901  // TODO: handle non-printing chars
902 
903  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
904  WB_ERROR_PRINT("TEMPORARY: %s - beep\n", __FUNCTION__);
905  }
906  else if(CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->has_select)(&(pE->xTextObject)) : 0)
907  {
908 // WB_ERROR_PRINT("TEMPORARY: %s - set text to \"%.*s\"\n", __FUNCTION__, nChar, pBuf);
909  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->set_text)(&(pE->xTextObject), pBuf, nChar);
910  internal_notify_change(pC, 0);
911  }
912  else
913  {
914 // WB_ERROR_PRINT("TEMPORARY: %s - inserting \"%.*s\"\n", __FUNCTION__, nChar, pBuf);
915  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->ins_chars)(&(pE->xTextObject), pBuf, nChar);
916  internal_notify_change(pC, 0);
917  }
918 
919 // {
920 // char *p1 = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_text)(&(pE->xTextObject)) : NULL;
921 //
922 // WB_ERROR_PRINT("TEMPORARY: %s - new text \"%s\"\n", __FUNCTION__, (const char *)(p1 ? p1 : "{null}"));
923 //
924 // if(p1)
925 // {
926 // WBFree(p1);
927 // }
928 // }
929 
930  internal_new_cursor_pos((WBEditWindow *)pC);
931 }
932 
933 static void internal_scancode(WBChildFrame *pC, XClientMessageEvent *pEvent)
934 {
935 WBEditWindow *pE = (WBEditWindow *)pC;
936 
937 
938  CALLBACK_TRACKER;
939 
940  if(!WBIsValidEditWindow(pE))
941  {
942  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
943 
944  return;
945  }
946 
947  // TODO: handle things I might want, like 'indent' which might be ctrl+[ or ctrl+], or maybe
948  // ctrl+tab or ctrl+shift+tab
949 
950 
951  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
952 }
953 
954 static void internal_bkspace(WBChildFrame *pC, int iACS)
955 {
956 WBEditWindow *pE = (WBEditWindow *)pC;
957 
958 
959  CALLBACK_TRACKER;
960 
961  if(!WBIsValidEditWindow(pE))
962  {
963  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
964 
965  return;
966  }
967 
968  if(iACS & WB_KEYEVENT_ACSMASK) // not handling ctrl, shift, or alt with backspace. yet.
969  {
970  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
971  }
972  else
973  {
974  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->del_chars)(&(pE->xTextObject), -1);
975  internal_notify_change(pC, 0);
976  }
977 
978  internal_new_cursor_pos((WBEditWindow *)pC);
979 }
980 
981 static void internal_del(WBChildFrame *pC, int iACS)
982 {
983 WBEditWindow *pE = (WBEditWindow *)pC;
984 
985 
986  CALLBACK_TRACKER;
987 
988  if(!WBIsValidEditWindow(pE))
989  {
990  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
991 
992  return;
993  }
994 
995  // shift+del does 'cut' behavior
996 
997  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // shift+del
998  {
999  if(!(CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->has_select)(&(pE->xTextObject)) : 0))
1000  {
1001  // no selection, can't "cut"
1002  XBell(WBGetWindowDisplay(pC->wID), -100);
1003  }
1004  else
1005  {
1006  // copy selection to the clipboard, then delete - same as internal_cut_to_cb()
1007 
1008  char *p1 = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_sel_text)(&(pE->xTextObject), NULL): NULL;
1009  if(p1)
1010  {
1011  WBSetClipboardData(WBGetWindowDisplay(pC->wID), aUTF8_STRING, 8, p1, strlen(p1) + 1);
1012 
1013  WBFree(p1);
1014 
1015  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->del_select)(&(pE->xTextObject));
1016  internal_notify_change(pC, 0);
1017  }
1018  }
1019  }
1020  else if(CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->has_select)(&(pE->xTextObject)) : 0)
1021  {
1022  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->del_select)(&(pE->xTextObject));
1023  internal_notify_change(pC, 0);
1024  }
1025  else
1026  {
1027  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->del_chars)(&(pE->xTextObject), 1);
1028  internal_notify_change(pC, 0);
1029  }
1030 
1031  internal_new_cursor_pos((WBEditWindow *)pC);
1032 }
1033 
1034 static void internal_tab(WBChildFrame *pC, int iACS)
1035 {
1036 WBEditWindow *pE = (WBEditWindow *)pC;
1037 
1038 
1039  CALLBACK_TRACKER;
1040 
1041  if(!WBIsValidEditWindow(pE))
1042  {
1043  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1044 
1045  return;
1046  }
1047 
1048  // if there's a selection, indent it??
1049 
1050  if(iACS & WB_KEYEVENT_ACSMASK) // not handling ctrl, shift, or alt with tab. yet.
1051  {
1052  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1053  }
1054  else
1055  {
1056  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->ins_chars)(&(pE->xTextObject), "\t", 1);
1057  internal_notify_change(pC, 0);
1058  }
1059 
1060  internal_new_cursor_pos((WBEditWindow *)pC);
1061 }
1062 
1063 static void internal_enter(WBChildFrame *pC, int iACS)
1064 {
1065 WBEditWindow *pE = (WBEditWindow *)pC;
1066 
1067 
1068  CALLBACK_TRACKER;
1069 
1070  if(!WBIsValidEditWindow(pE))
1071  {
1072  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1073 
1074  return;
1075  }
1076 
1077  if(iACS & WB_KEYEVENT_ACSMASK) // not handling ctrl, shift, or alt with 'enter'. yet.
1078  {
1079  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1080  }
1081  else
1082  {
1083  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->ins_chars)(&(pE->xTextObject), "\n", 1);
1084  internal_notify_change(pC, 0);
1085  }
1086 
1087  internal_new_cursor_pos((WBEditWindow *)pC);
1088 }
1089 
1090 static void internal_properties(WBChildFrame *pC)
1091 {
1092 WBEditWindow *pE = (WBEditWindow *)pC;
1093 WBDialogWindow *pDlg;
1094 int iX, iY;
1095 WB_GEOM geomParent;
1096 Window wIDDlg;
1097 struct _PROPERTY_DLG_ propdlg;
1098 static const char szPropertiesDlgBox[]=
1099  "BEGIN_DIALOG FONT:Variable HEIGHT:200 WIDTH:300 TITLE:\"Document Properties\"\n"
1100  " CONTROL:Text TITLE:\"Document Properties\" X:30 Y:2 WIDTH:240 HEIGHT:17 VISIBLE HALIGN_TEXT_CENTER VALIGN_TEXT_CENTER\n"
1101  " CONTROL:CheckButton ID:1001 TITLE:\"Use Hard _Tabs\" X:40 Y:38 WIDTH:80 HEIGHT:15 VISIBLE\n"
1102  " CONTROL:Text TITLE:\"Line ending:\" X:10 Y:51 WIDTH:60 HEIGHT:17 VISIBLE HALIGN_TEXT_RIGHT VALIGN_TEXT_CENTER NOBORDER\n"
1103  " CONTROL:FirstRadioButton ID:1002 TITLE:\"_LF\" X:70 Y:52 WIDTH:40 HEIGHT:15 VISIBLE HALIGN_TEXT_LEFT VALIGN_TEXT_CENTER CHECKED\n"
1104  " CONTROL:RadioButton ID:1003 TITLE:\"C_R\" X:110 Y:52 WIDTH:40 HEIGHT:15 HALIGN_TEXT_LEFT VALIGN_TEXT_CENTER VISIBLE\n"
1105  " CONTROL:RadioButton ID:1004 TITLE:\"_CR+LF\" X:150 Y:52 WIDTH:40 HEIGHT:15 HALIGN_TEXT_LEFT VALIGN_TEXT_CENTER VISIBLE\n"
1106  " CONTROL:DefPushButton ID:IDOK TITLE:Sa_ve X:80 Y:178 WIDTH:40 HEIGHT:18 VISIBLE\n"
1107  " CONTROL:CancelButton ID:IDCANCEL TITLE:Cancel X:180 Y:178 WIDTH:40 HEIGHT:18 VISIBLE\n"
1108  "END_DIALOG\n";
1109 
1110 
1111  CALLBACK_TRACKER;
1112 
1113  if(!WBIsValidEditWindow(pE))
1114  {
1115  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1116 
1117  return;
1118  }
1119 
1120  // TODO: check for owner-defined property dialog and display default if none
1121 
1122  WBGetWindowGeom0(pC->wID, &geomParent); // parent geometry in absolute coordinates
1123 
1124  iX = geomParent.x + geomParent.border + 50;
1125  iY = geomParent.y + geomParent.border - 50;
1126 
1127  propdlg.pEditWindow = pE; // custom data sent to dialog box
1128 
1129  pDlg = DLGCreateDialogWindow(pC->wID, "Document Properties", szPropertiesDlgBox, iX, iY,
1130  300, 200, // the values also specified in the resource
1131  PropertyDialogCallback,
1132  WBDialogWindow_VISIBLE, &propdlg);
1133 
1134 
1135  if(pDlg) // TODO: manage this stuff as part of 'DLGCreateDialogWindow' instead
1136  {
1137  wIDDlg = pDlg->wID;
1138 
1139 // WBSetWindowIcon(wIDDlg, ???);
1140 // WB_ERROR_PRINT("TEMPORARY: %s - calling WBShowModal\n", __FUNCTION__);
1141 
1142  if(WBShowModal(wIDDlg, 0) == IDOK)
1143  {
1145 // WBInvalidateGeom(pC->wID, NULL, 1); // invalidate and re-paint with new properties, etc. configured
1146  }
1147  }
1148 
1149 }
1150 
1151 static void internal_uparrow(WBChildFrame *pC, int iACS)
1152 {
1153 WBEditWindow *pE = (WBEditWindow *)pC;
1154 
1155 
1156  CALLBACK_TRACKER;
1157 
1158  if(!WBIsValidEditWindow(pE))
1159  {
1160  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1161 
1162  return;
1163  }
1164 
1165  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // shift-uparrow
1166  {
1167  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1168  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_up)(&(pE->xTextObject));
1169  }
1170  else if((iACS & WB_KEYEVENT_ACSMASK) == (WB_KEYEVENT_SHIFT | WB_KEYEVENT_CTRL)) // ctrl-shift-uparrow
1171  {
1172  // select to start of paragraph?
1173  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1174  }
1175  else if(iACS & WB_KEYEVENT_ACSMASK) // not handling ctrl, shift, or alt with 'up'. yet.
1176  {
1177  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1178  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1179  }
1180  else
1181  {
1182  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1183  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_up)(&(pE->xTextObject));
1184  }
1185 
1186  internal_new_cursor_pos((WBEditWindow *)pC);
1187 }
1188 
1189 static void internal_downarrow(WBChildFrame *pC, int iACS)
1190 {
1191 WBEditWindow *pE = (WBEditWindow *)pC;
1192 
1193 
1194  CALLBACK_TRACKER;
1195 
1196  if(!WBIsValidEditWindow(pE))
1197  {
1198  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1199 
1200  return;
1201  }
1202 
1203  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // shift-downarrow
1204  {
1205  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1206  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_down)(&(pE->xTextObject));
1207  }
1208  else if((iACS & WB_KEYEVENT_ACSMASK) == (WB_KEYEVENT_SHIFT | WB_KEYEVENT_CTRL)) // ctrl-shift-downarrow
1209  {
1210  // select to start of paragraph?
1211  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1212  }
1213  else if(iACS & WB_KEYEVENT_ACSMASK) // not handling ctrl, shift, or alt with 'up'. yet.
1214  {
1215  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1216  }
1217  else
1218  {
1219  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1220  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_down)(&(pE->xTextObject));
1221  }
1222 
1223  internal_new_cursor_pos((WBEditWindow *)pC);
1224 }
1225 
1226 static void internal_leftarrow(WBChildFrame *pC, int iACS)
1227 {
1228 WBEditWindow *pE = (WBEditWindow *)pC;
1229 
1230 
1231  CALLBACK_TRACKER;
1232 
1233  if(!WBIsValidEditWindow(pE))
1234  {
1235  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1236 
1237  return;
1238  }
1239 
1240  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // shift-leftarrow
1241  {
1242  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1243  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_left)(&(pE->xTextObject));
1244  }
1245  else if((iACS & WB_KEYEVENT_ACSMASK) == (WB_KEYEVENT_SHIFT | WB_KEYEVENT_CTRL)) // ctrl-shift-leftarrow
1246  {
1247  // select to start of previous word? end of previous word?
1248  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1249  }
1250  else if(iACS & WB_KEYEVENT_ACSMASK) // not handling ctrl, shift, or alt with 'left'. yet.
1251  {
1252  WB_ERROR_PRINT("TEMPORARY: %s - iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
1253 
1254  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1255  }
1256  else
1257  {
1258  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1259  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_left)(&(pE->xTextObject));
1260  }
1261 
1262  internal_new_cursor_pos((WBEditWindow *)pC);
1263 }
1264 
1265 static void internal_rightarrow(WBChildFrame *pC, int iACS)
1266 {
1267 WBEditWindow *pE = (WBEditWindow *)pC;
1268 
1269 
1270  CALLBACK_TRACKER;
1271 
1272  if(!WBIsValidEditWindow(pE))
1273  {
1274  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1275 
1276  return;
1277  }
1278 
1279  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // shift-rightarrow
1280  {
1281  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1282  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_right)(&(pE->xTextObject));
1283  }
1284  else if((iACS & WB_KEYEVENT_ACSMASK) == (WB_KEYEVENT_SHIFT | WB_KEYEVENT_CTRL)) // ctrl-shift-rightarrow
1285  {
1286  // select to end of word? start of next word?
1287  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1288  }
1289  else if(iACS & WB_KEYEVENT_ACSMASK) // not handling ctrl, shift, or alt with 'right'. yet.
1290  {
1291  WB_ERROR_PRINT("TEMPORARY: %s - iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
1292 
1293  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1294  }
1295  else
1296  {
1297  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1298  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_right)(&(pE->xTextObject));
1299  }
1300 
1301  internal_new_cursor_pos((WBEditWindow *)pC);
1302 }
1303 
1304 static void internal_home(WBChildFrame *pC, int iACS)
1305 {
1306 WBEditWindow *pE = (WBEditWindow *)pC;
1307 
1308 
1309  CALLBACK_TRACKER;
1310 
1311  if(!WBIsValidEditWindow(pE))
1312  {
1313  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1314 
1315  return;
1316  }
1317 
1318  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // shift-home
1319  {
1320  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1321  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_home)(&(pE->xTextObject));
1322  }
1323  else if((iACS & WB_KEYEVENT_ACSMASK) == (WB_KEYEVENT_SHIFT | WB_KEYEVENT_CTRL)) // ctrl-shift-home
1324  {
1325  // select to start of document
1326  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1327  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_top)(&(pE->xTextObject));
1328  }
1329  else if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_CTRL) // control+home
1330  {
1331  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1332  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_top)(&(pE->xTextObject));
1333  }
1334  else if(iACS & WB_KEYEVENT_ACSMASK) // not handling shift, or alt with 'home'. yet.
1335  {
1336  WB_ERROR_PRINT("TEMPORARY: %s - iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
1337 
1338  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1339  }
1340  else
1341  {
1342  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1343  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_home)(&(pE->xTextObject));
1344  }
1345 
1346  internal_new_cursor_pos((WBEditWindow *)pC);
1347 }
1348 
1349 static void internal_end(WBChildFrame *pC, int iACS)
1350 {
1351 WBEditWindow *pE = (WBEditWindow *)pC;
1352 
1353 
1354  CALLBACK_TRACKER;
1355 
1356  if(!WBIsValidEditWindow(pE))
1357  {
1358  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1359 
1360  return;
1361  }
1362 
1363  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // shift-end
1364  {
1365  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1366  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_end)(&(pE->xTextObject));
1367  }
1368  else if((iACS & WB_KEYEVENT_ACSMASK) == (WB_KEYEVENT_SHIFT | WB_KEYEVENT_CTRL)) // ctrl-shift-end
1369  {
1370  // select to end of document
1371  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1372  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_bottom)(&(pE->xTextObject));
1373  }
1374  else if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_CTRL) // control+end
1375  {
1376  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1377  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_bottom)(&(pE->xTextObject));
1378  }
1379  else if(iACS & WB_KEYEVENT_ACSMASK) // not handling shift, or alt with 'end'. yet.
1380  {
1381  WB_ERROR_PRINT("TEMPORARY: %s - iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
1382 
1383  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1384  }
1385  else
1386  {
1387  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1388  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->cursor_end)(&(pE->xTextObject));
1389  }
1390 
1391  internal_new_cursor_pos((WBEditWindow *)pC);
1392 }
1393 
1394 static void internal_pgup(WBChildFrame *pC, int iACS)
1395 {
1396 WBEditWindow *pE = (WBEditWindow *)pC;
1397 
1398 
1399  CALLBACK_TRACKER;
1400 
1401  if(!WBIsValidEditWindow(pE))
1402  {
1403  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1404 
1405  return;
1406  }
1407 
1408  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // shift-pgup
1409  {
1410  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1411  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->page_up)(&(pE->xTextObject));
1412  }
1413  else if(iACS & WB_KEYEVENT_ACSMASK) // not handling ctrl or alt. yet.
1414  {
1415  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1416  }
1417  else
1418  {
1419 // WB_ERROR_PRINT("TEMPORARY: %s - WBChildFrame calling 'page_up'\n", __FUNCTION__);
1420 
1421  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1422  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->page_up)(&(pE->xTextObject));
1423  }
1424 
1425  internal_new_cursor_pos((WBEditWindow *)pC);
1426 }
1427 
1428 static void internal_pgdown(WBChildFrame *pC, int iACS)
1429 {
1430 WBEditWindow *pE = (WBEditWindow *)pC;
1431 
1432 
1433  CALLBACK_TRACKER;
1434 
1435  if(!WBIsValidEditWindow(pE))
1436  {
1437  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1438 
1439  return;
1440  }
1441 
1442  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // shift-pgdown
1443  {
1444  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1445  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->page_down)(&(pE->xTextObject));
1446  }
1447  else if(iACS & WB_KEYEVENT_ACSMASK) // not handling ctrl or alt. yet.
1448  {
1449  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1450  }
1451  else
1452  {
1453 // WB_ERROR_PRINT("TEMPORARY: %s - WBChildFrame calling 'page_down'\n", __FUNCTION__);
1454 
1455  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1456  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->page_down)(&(pE->xTextObject));
1457  }
1458 
1459  internal_new_cursor_pos((WBEditWindow *)pC);
1460 }
1461 
1462 static void internal_pgleft(WBChildFrame *pC, int iACS)
1463 {
1464 WBEditWindow *pE = (WBEditWindow *)pC;
1465 
1466 
1467  CALLBACK_TRACKER;
1468 
1469  if(!WBIsValidEditWindow(pE))
1470  {
1471  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1472 
1473  return;
1474  }
1475 
1476  if((iACS & WB_KEYEVENT_ACSMASK) == (WB_KEYEVENT_SHIFT | WB_KEYEVENT_CTRL)) // ctrl-shift-pgup
1477  {
1478  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1479  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->page_left)(&(pE->xTextObject));
1480  }
1481  else if((iACS & WB_KEYEVENT_ACSMASK) != WB_KEYEVENT_CTRL) // not handling alt with 'pgup'. yet.
1482  {
1483  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1484  }
1485  else // CTRL-pgup
1486  {
1487  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1488  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->page_left)(&(pE->xTextObject));
1489  }
1490 
1491  internal_new_cursor_pos((WBEditWindow *)pC);
1492 }
1493 
1494 static void internal_pgright(WBChildFrame *pC, int iACS)
1495 {
1496 WBEditWindow *pE = (WBEditWindow *)pC;
1497 
1498 
1499  CALLBACK_TRACKER;
1500 
1501  if(!WBIsValidEditWindow(pE))
1502  {
1503  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1504 
1505  return;
1506  }
1507 
1508  if((iACS & WB_KEYEVENT_ACSMASK) == (WB_KEYEVENT_SHIFT | WB_KEYEVENT_CTRL)) // ctrl-shift-pgdn
1509  {
1510  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1511  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->page_right)(&(pE->xTextObject));
1512  }
1513  else if((iACS & WB_KEYEVENT_ACSMASK) != WB_KEYEVENT_CTRL) // not handling alt with 'pgup'. yet.
1514  {
1515  XBell(WBGetWindowDisplay(pC->wID), -100); // for now give audible feedback that I'm ignoring it
1516  }
1517  else
1518  {
1519  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_highlight)(&(pE->xTextObject)); // safe to call any time, multiple times
1520  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->page_right)(&(pE->xTextObject));
1521  }
1522 
1523  internal_new_cursor_pos((WBEditWindow *)pC);
1524 }
1525 
1526 static void internal_help(WBChildFrame *pC, int iACS)
1527 {
1528 WBEditWindow *pE = (WBEditWindow *)pC;
1529 
1530 
1531  CALLBACK_TRACKER;
1532 
1533  if(!WBIsValidEditWindow(pE))
1534  {
1535  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1536 
1537  return;
1538  }
1539 
1540 }
1541 
1542 static void internal_hover_notify(WBChildFrame *pC, int x, int y)
1543 {
1544 WBEditWindow *pE = (WBEditWindow *)pC;
1545 
1546 
1547  CALLBACK_TRACKER;
1548 
1549  if(!WBIsValidEditWindow(pE))
1550  {
1551  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1552 
1553  return;
1554  }
1555 
1556 }
1557 
1558 static void internal_hover_cancel(WBChildFrame *pC)
1559 {
1560 WBEditWindow *pE = (WBEditWindow *)pC;
1561 
1562 
1563  CALLBACK_TRACKER;
1564 
1565  if(!WBIsValidEditWindow(pE))
1566  {
1567  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1568 
1569  return;
1570  }
1571 
1572 }
1573 
1574 static int internal_is_ins_mode(WBChildFrame *pC)
1575 {
1576 WBEditWindow *pE = (WBEditWindow *)pC;
1577 
1578 
1579  CALLBACK_TRACKER;
1580 
1581  if(!WBIsValidEditWindow(pE))
1582  {
1583  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1584 
1585  return -1;
1586  }
1587 
1588  return (CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_insmode)(&(pE->xTextObject)) : InsertMode_INSERT)
1589  == InsertMode_INSERT;
1590 }
1591 
1592 static void internal_toggle_ins_mode(WBChildFrame *pC)
1593 {
1594 WBEditWindow *pE = (WBEditWindow *)pC;
1595 int iInsMode;
1596 
1597 
1598  CALLBACK_TRACKER;
1599 
1600  if(!WBIsValidEditWindow(pE))
1601  {
1602  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1603 
1604  return;
1605  }
1606 
1607  iInsMode = (CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_insmode)(&(pE->xTextObject)) : InsertMode_INSERT)
1608  == InsertMode_INSERT;
1609  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->set_insmode)(&(pE->xTextObject), iInsMode ? InsertMode_OVERWRITE : InsertMode_INSERT);
1610 
1611  internal_new_cursor_pos((WBEditWindow *)pC);
1612  internal_update_status_text(pE);
1613 }
1614 
1615 static void internal_copy_to_cb(WBChildFrame *pC)
1616 {
1617 WBEditWindow *pE = (WBEditWindow *)pC;
1618 char *p1;
1619 
1620 
1621  CALLBACK_TRACKER;
1622 
1623  if(!WBIsValidEditWindow(pE))
1624  {
1625  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1626 
1627  return;
1628  }
1629 
1630  // copy selection to the clipboard
1631 
1632  if(CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->has_select)(&(pE->xTextObject)) : 0)
1633  {
1634  p1 = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_sel_text)(&(pE->xTextObject), NULL) : NULL;
1635 
1636  if(p1)
1637  {
1638  WBSetClipboardData(WBGetWindowDisplay(pC->wID), aUTF8_STRING, 8, p1, strlen(p1) + 1);
1639 
1640  WBFree(p1);
1641  }
1642  }
1643  else
1644  {
1645  // no selection, can't "copy"
1646 
1647  XBell(WBGetWindowDisplay(pC->wID), -100);
1648  }
1649 }
1650 
1651 static void internal_paste_from_cb(WBChildFrame *pC)
1652 {
1653 WBEditWindow *pE = (WBEditWindow *)pC;
1654 Atom aType = aUTF8_STRING;
1655 int iFormat = 8;
1656 unsigned long nData = 0;
1657 char *p1;
1658 
1659 
1660  CALLBACK_TRACKER;
1661 
1662  if(!WBIsValidEditWindow(pE))
1663  {
1664  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1665 
1666  return;
1667  }
1668 
1669  // copy selection to the clipboard, then delete - same as internal_cut_to_cb()
1670 
1671  p1 = (char *)WBGetClipboardData(WBGetWindowDisplay(pC->wID), &aType, &iFormat, &nData);
1672  if(!p1) // try regular string, not UTF8
1673  {
1674  aType = aSTRING;
1675  p1 = (char *)WBGetClipboardData(WBGetWindowDisplay(pC->wID), &aType, &iFormat, &nData);
1676  }
1677 
1678  if(p1 && nData > 0)
1679  {
1680  if(!p1[nData - 1])
1681  {
1682  nData--;
1683  }
1684  }
1685 
1686 
1687  if(p1)
1688  {
1689  // TODO: convert to correct format (ASCII)
1690  if(iFormat != 8) // 16-bit unicode is assumed now
1691  {
1692  if(iFormat == 8 * sizeof(wchar_t))
1693  {
1694  char *pNew = WBAlloc(sizeof(wchar_t) * (nData + 2));
1695  if(pNew)
1696  {
1697  bzero(pNew, sizeof(wchar_t) * (nData + 2));
1698  wcstombs(pNew, (const wchar_t *)p1, sizeof(wchar_t) * (nData + 2));
1699  }
1700 
1701  WBFree(p1);
1702  p1 = pNew;
1703  nData = strlen(p1);
1704  }
1705  else
1706  {
1707  XBell(WBGetWindowDisplay(pC->wID), -100);
1708  WB_ERROR_PRINT("TEMPORARY - %s - clipboard format %d, can't 'PASTE'\n", __FUNCTION__, iFormat);
1709 
1710  WBFree(p1);
1711  p1 = NULL; // by convention - also, checked in next section
1712  }
1713  }
1714 
1715  if(p1)
1716  {
1717  WBDebugDump("Edit window 'paste'", p1, nData);
1718 
1719  if(CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->has_select)(&(pE->xTextObject)) : 0)
1720  {
1721  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->replace_select)(&(pE->xTextObject), p1, nData);
1722  internal_notify_change(pC, 0);
1723  }
1724  else
1725  {
1726  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->ins_chars)(&(pE->xTextObject), p1, nData);
1727  internal_notify_change(pC, 0);
1728  }
1729 
1730  WBFree(p1);
1731  p1 = NULL; // by convention
1732  }
1733  }
1734 
1735  internal_new_cursor_pos((WBEditWindow *)pC);
1736 }
1737 
1738 static void internal_cut_to_cb(WBChildFrame *pC)
1739 {
1740 WBEditWindow *pE = (WBEditWindow *)pC;
1741 
1742 
1743  CALLBACK_TRACKER;
1744 
1745  if(!WBIsValidEditWindow(pE))
1746  {
1747  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1748 
1749  return;
1750  }
1751 
1752  if(!(CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->has_select)(&(pE->xTextObject)) : 0))
1753  {
1754  // no selection, can't "cut"
1755  XBell(WBGetWindowDisplay(pC->wID), -100);
1756  }
1757  else
1758  {
1759  // copy selection to the clipboard, then delete - same as internal_cut_to_cb()
1760 
1761  char *p1 = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_sel_text)(&(pE->xTextObject), NULL) : NULL;
1762  if(p1)
1763  {
1764  WBSetClipboardData(WBGetWindowDisplay(pC->wID), aUTF8_STRING, 8, p1, strlen(p1) + 1);
1765 
1766  WBFree(p1);
1767 
1768  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->del_select)(&(pE->xTextObject));
1769  internal_notify_change(pC, 0);
1770  }
1771  }
1772 
1773  internal_new_cursor_pos((WBEditWindow *)pC);
1774 }
1775 
1776 static void internal_delete_sel(WBChildFrame *pC)
1777 {
1778 WBEditWindow *pE = (WBEditWindow *)pC;
1779 
1780 
1781  CALLBACK_TRACKER;
1782 
1783  if(!WBIsValidEditWindow(pE))
1784  {
1785  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1786 
1787  return;
1788  }
1789 
1790  if(!(CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->has_select)(&(pE->xTextObject)) : 0))
1791  {
1792  // no selection, can't "cut"
1793  XBell(WBGetWindowDisplay(pC->wID), -100);
1794  }
1795  else
1796  {
1797  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->del_select)(&(pE->xTextObject));
1798  internal_notify_change(pC, 0);
1799  }
1800 
1801  internal_new_cursor_pos((WBEditWindow *)pC);
1802 }
1803 
1804 static void internal_select_all(WBChildFrame *pC)
1805 {
1806 WBEditWindow *pE = (WBEditWindow *)pC;
1807 WB_RECT rct;
1808 
1809 
1810  CALLBACK_TRACKER;
1811 
1812  if(!WBIsValidEditWindow(pE))
1813  {
1814  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1815 
1816  return;
1817  }
1818 
1819  rct.left = rct.top = 0;
1820  rct.right = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_cols)(&(pE->xTextObject)) : 0;
1821  rct.bottom = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_rows)(&(pE->xTextObject)) : 0;
1822 
1823  WB_ERROR_PRINT("TEMPORARY: %s - selecting %d,%d,%d,%d\n", __FUNCTION__,
1824  rct.left, rct.top, rct.right, rct.bottom);
1825 
1826  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->set_select)(&(pE->xTextObject), &rct); // select 'all'
1827 
1828 //#if 1
1829 // CALLBACK_CHECK_NULL(pE->xTextObject.vtable->get_select)(&(pE->xTextObject), &rct); // get selection for testing
1830 //
1831 // WB_ERROR_PRINT("TEMPORARY: %s - selected %d,%d,%d,%d\n", __FUNCTION__,
1832 // rct.left, rct.top, rct.right, rct.bottom);
1833 //#endif // 1
1834 
1835  internal_new_cursor_pos((WBEditWindow *)pC);
1836 }
1837 
1838 static void internal_select_none(WBChildFrame *pC)
1839 {
1840 WBEditWindow *pE = (WBEditWindow *)pC;
1841 
1842 
1843  CALLBACK_TRACKER;
1844 
1845  if(!WBIsValidEditWindow(pE))
1846  {
1847  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1848 
1849  return;
1850  }
1851 
1852  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->set_select)(&(pE->xTextObject), NULL);
1853 
1854  internal_new_cursor_pos((WBEditWindow *)pC);
1855 }
1856 
1857 static void internal_save(WBChildFrame *pC, const char *szFileName)
1858 {
1859 WBEditWindow *pE = (WBEditWindow *)pC;
1860 
1861 
1862  CALLBACK_TRACKER;
1863 
1864  if(!WBIsValidEditWindow(pE))
1865  {
1866  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1867 
1868  return;
1869  }
1870 
1871  WBEditWindowSaveFile(pE, szFileName);
1872 }
1873 
1874 static WB_PCSTR internal_get_file_name(WBChildFrame *pC)
1875 {
1876 WBEditWindow *pE = (WBEditWindow *)pC;
1877 
1878 
1879  CALLBACK_TRACKER;
1880 
1881  if(!WBIsValidEditWindow(pE))
1882  {
1883  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1884 
1885  return NULL;
1886  }
1887 
1888  return pE->szFileName;
1889 }
1890 
1891 static void internal_mouse_click(WBChildFrame *pC, int iX, int iY, int iButtonMask, int iACS)
1892 {
1893 WBEditWindow *pE = (WBEditWindow *)pC;
1894 
1895 
1896  CALLBACK_TRACKER;
1897 
1898  if(!WBIsValidEditWindow(pE))
1899  {
1900  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1901 
1902  return;
1903  }
1904 
1905  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->mouse_click)(&(pE->xTextObject), iX, iY, iButtonMask, iACS);
1906 
1907  internal_new_cursor_pos((WBEditWindow *)pC);
1908 }
1909 
1910 static void internal_mouse_dblclick(WBChildFrame *pC, int iX, int iY, int iButtonMask, int iACS)
1911 {
1912 WBEditWindow *pE = (WBEditWindow *)pC;
1913 
1914 
1915  CALLBACK_TRACKER;
1916 
1917  if(!WBIsValidEditWindow(pE))
1918  {
1919  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1920 
1921  return;
1922  }
1923 
1924  // TODO: select the current 'word'?
1925 
1926  internal_new_cursor_pos((WBEditWindow *)pC);
1927 }
1928 
1929 static void internal_mouse_drag(WBChildFrame *pC, int iX, int iY, int iButtonMask, int iACS)
1930 {
1931 WBEditWindow *pE = (WBEditWindow *)pC;
1932 
1933 
1934  CALLBACK_TRACKER;
1935 
1936  if(!WBIsValidEditWindow(pE))
1937  {
1938  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1939 
1940  return;
1941  }
1942 
1943  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->begin_mouse_drag)(&(pE->xTextObject));
1944 
1945  internal_new_cursor_pos((WBEditWindow *)pC);
1946 }
1947 
1948 static void internal_mouse_drop(WBChildFrame *pC, int iX, int iY, int iButtonMask, int iACS)
1949 {
1950 WBEditWindow *pE = (WBEditWindow *)pC;
1951 
1952 
1953  CALLBACK_TRACKER;
1954 
1955  if(!WBIsValidEditWindow(pE))
1956  {
1957  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1958 
1959  return;
1960  }
1961 
1962  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->end_mouse_drag)(&(pE->xTextObject));
1963 
1964  internal_new_cursor_pos((WBEditWindow *)pC);
1965 }
1966 
1967 static void internal_mouse_move(WBChildFrame *pC, int iX, int iY)
1968 {
1969 WBEditWindow *pE = (WBEditWindow *)pC;
1970 
1971 
1972  CALLBACK_TRACKER;
1973 
1974  if(!WBIsValidEditWindow(pE))
1975  {
1976  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1977 
1978  return;
1979  }
1980 
1981  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->mouse_click)(&(pE->xTextObject), iX, iY, 0, 0); // report mouse motion
1982 
1983  internal_new_cursor_pos((WBEditWindow *)pC);
1984 }
1985 
1986 static void internal_scroll_vert(WBChildFrame *pC, int iMode, int iValue)
1987 {
1988 WBEditWindow *pE = (WBEditWindow *)pC;
1989 
1990  CALLBACK_TRACKER;
1991 
1992  if(!WBIsValidEditWindow(pE))
1993  {
1994  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
1995 
1996  return;
1997  }
1998 
1999  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_ScrollBar,
2000  "%s %d - iMode=%d, iValue=%d\n", __FUNCTION__, __LINE__, iMode, iValue);
2001 
2002  // TODO: check scroll mode for scroll lock?
2003 
2004  if(iMode == 0) // absolute
2005  {
2006  if(pE->xTextObject.vtable->get_view)
2007  {
2008  WB_RECT rctView;
2009  WB_POINT ptScroll;
2010 
2011  pE->xTextObject.vtable->get_view(&(pE->xTextObject), &rctView);
2012 
2013  if(iValue == rctView.top) // not moving
2014  {
2015  return;
2016  }
2017 
2018  ptScroll.x = rctView.left;
2019  ptScroll.y = iValue;
2020 
2021  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->set_view_orig)(&(pE->xTextObject), &ptScroll);
2022 
2023  FWSetChildFrameScrollInfo(pC, ptScroll.y, pC->extent.height,
2024  pC->origin.x, pC->extent.width,
2025  pC->iRowHeight, pC->iColWidth);
2026  }
2027  }
2028  else
2029  {
2030  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->scroll_vertical)(&(pE->xTextObject), iValue);
2031 
2033  CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_row)(&(pE->xTextObject))
2034  : pC->origin.y,
2035  pC->extent.height,
2036  pC->origin.x, pC->extent.width,
2037  pC->iRowHeight, pC->iColWidth);
2038  }
2039 
2040  internal_new_cursor_pos((WBEditWindow *)pC);
2041 }
2042 
2043 static void internal_scroll_horiz(WBChildFrame *pC, int iMode, int iValue)
2044 {
2045 WBEditWindow *pE = (WBEditWindow *)pC;
2046 
2047 
2048  CALLBACK_TRACKER;
2049 
2050  if(!WBIsValidEditWindow(pE))
2051  {
2052  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
2053 
2054  return;
2055  }
2056 
2057  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_ScrollBar,
2058  "%s %d - iMode=%d, iValue=%d\n", __FUNCTION__, __LINE__, iMode, iValue);
2059 
2060  // TODO: check scroll mode for scroll lock?
2061 
2062  if(iMode == 0) // absolute
2063  {
2064  if(pE->xTextObject.vtable->get_view)
2065  {
2066  WB_RECT rctView;
2067  WB_POINT ptScroll;
2068 
2069  pE->xTextObject.vtable->get_view(&(pE->xTextObject), &rctView);
2070 
2071  if(iValue == rctView.left) // not moving
2072  {
2073  return;
2074  }
2075 
2076  ptScroll.x = iValue;
2077  ptScroll.y = rctView.top;
2078 
2079  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->set_view_orig)(&(pE->xTextObject), &ptScroll);
2080 
2082  ptScroll.x, pC->extent.width,
2083  pC->iRowHeight, pC->iColWidth);
2084  }
2085  }
2086  else
2087  {
2088  CALLBACK_CHECK_NULL(pE->xTextObject.vtable->scroll_horizontal)(&(pE->xTextObject), iValue);
2089 
2091  CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_col)(&(pE->xTextObject))
2092  : pC->origin.x,
2093  pC->extent.width,
2094  pC->iRowHeight, pC->iColWidth);
2095  }
2096 
2097  internal_new_cursor_pos((WBEditWindow *)pC);
2098 }
2099 
2100 static void internal_mouse_cancel(WBChildFrame *pC)
2101 {
2102 WBEditWindow *pE = (WBEditWindow *)pC;
2103 
2104 
2105  CALLBACK_TRACKER;
2106 
2107  if(!WBIsValidEditWindow(pE))
2108  {
2109  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
2110 
2111  return;
2112  }
2113 
2114 
2115  internal_new_cursor_pos((WBEditWindow *)pC);
2116 }
2117 
2118 static void internal_get_row_col(WBChildFrame *pC, int *piR, int *piC)
2119 {
2120 WBEditWindow *pE = (WBEditWindow *)pC;
2121 
2122 
2123  CALLBACK_TRACKER;
2124 
2125  if(!WBIsValidEditWindow(pE))
2126  {
2127  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
2128 
2129  return;
2130  }
2131 
2132  if(piC)
2133  {
2134  *piC = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_col)(&(pE->xTextObject)) : 0;
2135  }
2136 
2137  if(piR)
2138  {
2139  *piR = CALLBACK_CHECK_NULL2(pE->xTextObject.vtable->get_row)(&(pE->xTextObject)) : 0;
2140  }
2141 }
2142 
2143 static int internal_has_selection(WBChildFrame *pC)
2144 {
2145 WBEditWindow *pE = (WBEditWindow *)pC;
2146 
2147 
2148  CALLBACK_TRACKER;
2149 
2150  if(!WBIsValidEditWindow(pE))
2151  {
2152  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
2153 
2154  return 0;
2155  }
2156 
2157  if(pE->xTextObject.vtable->get_select)
2158  {
2159  WB_RECT rctSel;
2160 
2161  pE->xTextObject.vtable->get_select(&(pE->xTextObject), &rctSel);
2162 
2163 // WB_ERROR_PRINT("TEMPORARY: %s - selection rectangle %d,%d,%d,%d\n", __FUNCTION__,
2164 // rctSel.left, rctSel.top, rctSel.right, rctSel.bottom);
2165 
2166  if(rctSel.left != rctSel.right || rctSel.bottom != rctSel.top) // NOT empty
2167  {
2168  return 1; // has a selection
2169  }
2170  }
2171 
2172  return 0; // no current selection
2173 }
2174 
2175 static void internal_undo(WBChildFrame *pC)
2176 {
2177 WBEditWindow *pE = (WBEditWindow *)pC;
2178 
2179 
2180  CALLBACK_TRACKER;
2181 
2182  if(!WBIsValidEditWindow(pE))
2183  {
2184  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
2185 
2186  return;
2187  }
2188 
2189  // perform an un-do operation
2190 }
2191 
2192 static void internal_redo(WBChildFrame *pC)
2193 {
2194 WBEditWindow *pE = (WBEditWindow *)pC;
2195 
2196 
2197  CALLBACK_TRACKER;
2198 
2199  if(!WBIsValidEditWindow(pE))
2200  {
2201  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
2202 
2203  return;
2204  }
2205 
2206  // perform a re-do operation
2207 }
2208 
2209 static int internal_can_undo(WBChildFrame *pC)
2210 {
2211 WBEditWindow *pE = (WBEditWindow *)pC;
2212 
2213 
2214  CALLBACK_TRACKER;
2215 
2216  if(!WBIsValidEditWindow(pE))
2217  {
2218  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
2219 
2220  return 0;
2221  }
2222 
2223  return 0; // can't un-do
2224 }
2225 
2226 static int internal_can_redo(WBChildFrame *pC)
2227 {
2228 WBEditWindow *pE = (WBEditWindow *)pC;
2229 
2230 
2231  CALLBACK_TRACKER;
2232 
2233  if(!WBIsValidEditWindow(pE))
2234  {
2235  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
2236 
2237  return 0;
2238  }
2239 
2240  return 0; // can't re-do
2241 }
2242 
2243 
2244 static int internal_is_empty(WBChildFrame *pC)
2245 {
2246 WBEditWindow *pE = (WBEditWindow *)pC;
2247 
2248 
2249  CALLBACK_TRACKER;
2250 
2251  if(!WBIsValidEditWindow(pE))
2252  {
2253  WB_ERROR_PRINT("ERROR: %s - WBChildFrame and/or WBEditWindow not valid, %p\n", __FUNCTION__, pE);
2254 
2255  return -1; // return '-1' on error
2256  }
2257 
2258  // if the contents are NOT NULL, it's not 'empty'
2259 
2260  if((pE->xTextObject.vtable->get_rows && pE->xTextObject.vtable->get_rows(&(pE->xTextObject)) > 0) ||
2261  (pE->xTextObject.vtable->get_cols && pE->xTextObject.vtable->get_cols(&(pE->xTextObject)) > 0))
2262  {
2263  return 0; // NOT empty
2264  }
2265 
2266  return 1; // empty (for now; later, do I dive directly into xTextObject ??? new API for vtable?)
2267 }
2268 
2269 
2270 
2271 // Properties dialog
2272 
2273 static int PropertyDialogCallback(Window wID, XEvent *pEvent)
2274 {
2276 //struct _PROPERTY_DLG_ *pUserData = (struct _PROPERTY_DLG_ *)(pDlg ? pDlg->pUserData : NULL);
2277 
2278 
2279  if(pEvent->type == ClientMessage && pEvent->xclient.message_type == aDIALOG_INIT)
2280  {
2281  if(!pDlg)
2282  {
2283  WB_ERROR_PRINT("%s - no WBDialogWindow structure in DIALOG_INIT for %d (%08xH) %p %08xH %08xH\n", __FUNCTION__,
2284  (unsigned int)wID, (unsigned int)wID, WBGetWindowData(wID, 0), DIALOG_WINDOW_TAG, ((WBDialogWindow *)WBGetWindowData(wID, 0))->ulTag);
2285  return 0; // can't process any messages now
2286  }
2287  else
2288  {
2289 // // assigning the correct icon
2290 //
2291 // Window wIDIcon = DLGGetDialogControl(pDlg, 1000); // ID 1000 for icon
2292 // WBDialogControl *pCtrl = DLGGetDialogControlStruct(wIDIcon);
2293 //
2294 // if(pCtrl)
2295 // {
2296 // Pixmap pixmap2 = None;
2297 // Pixmap pixmap = PXM_GetIconPixmap(GetMessageBoxIconPixmapID(pUserData->iType & MessageBox_ICON_MASK),
2298 // NULL, &pixmap2);
2299 //
2300 // if(pixmap != None)
2301 // {
2302 // WBDialogControlSetIconPixmap(pCtrl, pixmap, pixmap2);
2303 // }
2304 // }
2305  }
2306 
2307 // // assign the caption text to the caption window (which varies and must be assigned at run time)
2308 //
2309 // DLGSetControlCaption((WBDialogWindow *)pDlg, 1001, pUserData->szMessage);
2310 
2311  return 1;
2312  }
2313 
2314  if(!pDlg)
2315  {
2316  WB_WARN_PRINT("MessageBoxCallback - no WBDialogWindow structure\n");
2317  return 0; // can't process any messages now
2318  }
2319 
2320  if(pEvent->type == ClientMessage && pEvent->xclient.message_type == aCONTROL_NOTIFY)
2321  {
2322  WB_DEBUG_PRINT(DebugLevel_Light | DebugSubSystem_Event | DebugSubSystem_Dialog,
2323  "%s - MessageBox ClientMessage CONTROL_NOTIFY\n", __FUNCTION__);
2324 
2325  switch(pEvent->xclient.data.l[1]) // control ID
2326  {
2327  case IDOK:
2328  // TODO: save data
2329 
2330  case IDCANCEL:
2331  if(pEvent->xclient.data.l[0] == aBUTTON_PRESS)
2332  {
2333  WBEndModal(wID, pEvent->xclient.data.l[1]);
2334  }
2335 
2336  break;
2337 
2338  default:
2339  WB_WARN_PRINT("%s - MessageBox ClientMessage CONTROL_NOTIFY client id=%lx\n",
2340  __FUNCTION__, pEvent->xclient.data.l[1]);
2341  }
2342  }
2343 
2344  return 0;
2345 }
2346 
const char * CHGetHighlightForegroundColor(Display *pDisplay)
returns highlight foreground color
Definition: conf_help.c:3409
#define IDOK
Window wID
Window id for the frame window.
Definition: frame_window.h:277
WBWinEvent pUserCallback
message callback function pointer (can be NULL)
Definition: frame_window.h:458
char *(* get_sel_text)(const TEXT_OBJECT *pThis, const WB_RECT *pRct)
get the current selection rectangle as WB_RECT
Definition: text_object.h:416
void(* begin_mouse_drag)(TEXT_OBJECT *pThis)
Begin a mouse 'drag' operation.
Definition: text_object.h:590
void(* do_expose)(TEXT_OBJECT *pThis, Display *pDisplay, Window wID, WBGC gc, const WB_GEOM *pPaintGeom, const WB_GEOM *pViewGeom, WB_FONTC pFont)
Member function to properly render the text in a window (Expose event)
Definition: text_object.h:710
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
WBChildFrame childframe
elements common to a 'child frame' (derived object)
Definition: edit_window.h:160
void(* page_up)(TEXT_OBJECT *pThis)
Move the current cursor position up one page.
Definition: text_object.h:625
int FWInitChildFrame(WBChildFrame *pChildFrame, WBFrameWindow *pOwner, WB_FONTC pFont, const char *szFocusMenu, const WBFWMenuHandler *pHandlerArray, WBWinEvent pUserCallback, int fFlags)
Initialize a child frame (assumed to be a base 'class' for the window)
Definition: child_frame.c:118
void(* mouse_click)(TEXT_OBJECT *pThis, int iMouseXDelta, int iMouseYDelta, int iType, int iACS)
Translate mouse cursor position into actual row/column. This function is irrelevant if the expose met...
Definition: text_object.h:580
#define WB_DEBUG_PRINT(L,...)
Preferred method of implementing conditional debug output.
Definition: debug_helper.h:364
void * WBGetWindowData(Window wID, int iIndex)
Gets the data associated with this window and the specified index.
unsigned int width
the 'width' value of the extent.
int WBFontAscent(WB_FONTC pFont0)
Get the maximum character ascent from a WB_FONT.
Definition: font_helper.c:495
Utilities for copying and drawing text, determining text extents, and so on.
WBEditWindow * WBCreateEditWindow(WBFrameWindow *pOwner, WB_FONT pFont, const char *szFocusMenu, const WBFWMenuHandler *pHandlerArray, int fFlags)
Create an Edit Window.
Definition: edit_window.c:276
int x
the 'x' value of the point. can be negative.
int(* get_insmode)(const TEXT_OBJECT *pThis)
Get the current insert mode for the object.
Definition: text_object.h:324
OVERWRITE mode, character inserted on top of character to the right of the cursor (if any),...
Definition: text_object.h:169
int WBFontAvgCharWidth(WB_FONTC pFont0)
Get the average character width for a font.
Definition: font_helper.c:343
Icon - white question mark in green triangle.
void(* set_insmode)(TEXT_OBJECT *pThis, int iInsMode)
Set the current insert mode for the object.
Definition: text_object.h:331
WBWinEvent pUserCallback
user callback function to receive notifications and unhandled messages
Definition: edit_window.h:172
structure for managing menu callbacks
Definition: frame_window.h:217
void(* del_select)(TEXT_OBJECT *pThis)
Delete the current selection assigned via 'set_select'.
Definition: text_object.h:452
int FWGetChildFrameIndex(WBFrameWindow *pFW, WBChildFrame *pCont)
Sets the focus to a specific contained window using its tab order index.
char * szFileName
malloc'd name of file associated with this edit window (NULL if none)
Definition: edit_window.h:164
int WBShowModal(Window wID, int bMenuSplashFlag)
Shows a 'modal' window by processing events until the window closes.
void(* set_text)(TEXT_OBJECT *pThis, const char *szText, unsigned long cbLen)
Call this function to re-assign all text in the control.
Definition: text_object.h:256
Edit Window API functions.
void WBGetWindowGeom0(Window wID, WB_GEOM *pGeom)
Returns the ABSOLUTE window geometry relative to the screen.
Window wID
window identifier for the 'Child Frame' window. may contain 'None' while being destroyed
Definition: frame_window.h:429
void(* get_view)(const TEXT_OBJECT *pThis, WB_RECT *pRct)
Get the current viewport (in characters). The return value is not relevant if the expose method has n...
Definition: text_object.h:527
unsigned int border
static __inline__ void WBInitializeInPlaceTextObject(TEXT_OBJECT *pTextObject, Window wIDOwner)
initialize an 'in-place' TEXT_OBJECT structure
Definition: text_object.h:1045
unsigned long long WBGetFileModDateTime(const char *szFileName)
Obtain the 'time_t' value for a file's modification date/time (unix time, seconds since the epoch)
Definition: file_help.c:1609
unsigned int width
void(* set_select)(TEXT_OBJECT *pThis, const WB_RECT *pRct)
Set the current selection rectangle as WB_RECT.
Definition: text_object.h:396
int(* get_col)(const TEXT_OBJECT *pThis)
Get the current column cursor for the object.
Definition: text_object.h:435
void WBDebugDump(const char *szTitle, void *pData, int cbData)
conditionally dumps binary data to debug message output
#define CHILD_FRAME_UI_TAG
TAG for the WBChildFrameUI structure.
Definition: child_frame.h:99
Button Bits - Yes button plus No button.
int WBTextObjectCalculateLineHeight(int iAscent, int iDescent)
Calculate the correct per-line height (in pixels) for a specified font ascent and descent.
Definition: text_object.c:864
void(* end_highlight)(TEXT_OBJECT *pThis)
End a highlight block.
Definition: text_object.h:562
Button Bits - OK button.
static __inline__ Display * WBGetDefaultDisplay(void)
Returns the default Display.
internal wrapper struct for X11 'geometry' definition
'configuration helper' main header file for the X11 Work Bench Toolkit API
void FWChildFrameStatusChanged(WBChildFrame *pChildFrame)
Notify Child Frame to update status text in Frame Window.
Definition: child_frame.c:897
Atom aRECALC_LAYOUT
notify window that it should re-calculate things like scrollbars and viewports
void(* get_select)(const TEXT_OBJECT *pThis, WB_RECT *pRct)
Get the current selection rectangle as WB_RECT.
Definition: text_object.h:389
void(* page_right)(TEXT_OBJECT *pThis)
Move the current cursor position right one page.
Definition: text_object.h:640
unsigned int ulTag
'Tag' identifying this structure as a WBEditWindow
Definition: edit_window.h:162
Atom aDIALOG_INIT
DIALOG_INIT ClientMessage, sent to dialog window callback on frame create.
void(* page_down)(TEXT_OBJECT *pThis)
Move the current cursor position down one page.
Definition: text_object.h:630
int(* get_rows)(const TEXT_OBJECT *pThis)
Call this function to obtain the total number of rows for display purposes.
Definition: text_object.h:268
int WBSetForeground(WBGC hGC, unsigned long foreground)
Assign foreground color, a wrapper for XSetForeground()
int WBSetClipboardData(Display *pDisplay, Atom aType, int iFormat, const void *pData, unsigned long nData)
Get clipboard data of requested type.
void(* set_col)(TEXT_OBJECT *pThis, int iCol)
Set the current column cursor for the object.
Definition: text_object.h:446
WBDialogWindow * DLGCreateDialogWindow(Window wIDOwner, const char *szTitle, const char *szDialogResource, int iX, int iY, int iWidth, int iHeight, WBWinEvent pUserCallback, int iFlags, void *pUserData)
create a dialog window using a text resource
#define COPY_COLOR_NAME(X, Y, Z)
macro to get a color name or use default if it does not exist in settings
Atom aEW_EDIT_CHANGE
'Edit Change' notification to user-callback, sent via ClientMessage event
Definition: edit_window.c:210
Structure identifying a dialog (frame) window.
Icon - red stop sign.
#define IDYES
void DeleteTimer(Display *pDisplay, Window wID, long lID)
Deletes an existing timer's resources.
int WBCheckFileModDateTime(const char *szFileName, unsigned long long tVal)
Compare a 64-bit unsigned integer value against a file's modification date/time (unix time,...
Definition: file_help.c:1635
void FWChildFrameRecalcLayout(WBChildFrame *pChildFrame)
Child frame notification callback (called by frame window)
Definition: child_frame.c:845
#define DIALOG_WINDOW_TAG
Structure that defines an Edit Window.
Definition: edit_window.h:158
void(* cursor_home)(TEXT_OBJECT *pThis)
Move the cursor 'home' (left or BOL)
Definition: text_object.h:645
void WBEditWindowRegisterCallback(WBEditWindow *pEditWindow, WBWinEvent pUserCallback)
Clear the contents in the Edit Window, and NULL the stored file name.
Definition: edit_window.c:578
static __inline__ WBChildFrame * FWGetChildFrameStruct(Window wID)
Obtain the associated WBChildFrame structure pointer for a Window ID.
Definition: child_frame.h:376
WB_POINT origin
viewport 'origin' in 'client units' (such as chars and lines) - determines scroll behavior
Definition: frame_window.h:435
WB_EXTENT extent
viewport 'extent' in 'client units' (such as chars and lines) - determines scroll behavior
Definition: frame_window.h:436
const char * CHGetTextColor(Display *pDisplay)
returns text color
Definition: conf_help.c:3399
size_t WBReadFileIntoBuffer(const char *szFileName, char **ppBuf)
read a file's contents into a buffer, returning the length of the buffer
Definition: file_help.c:572
void * WBAlloc(int nSize)
High performance memory sub-allocator 'allocate'.
void(* cursor_right)(TEXT_OBJECT *pThis)
Move the current cursor position right one column.
Definition: text_object.h:620
void(* set_view_orig)(TEXT_OBJECT *pThis, const WB_POINT *pOrig)
Set the current viewport (in characters). Only 'left' and 'top' are relevant if the expose method has...
Definition: text_object.h:539
char * szStatusText
Status text ('WBAlloc'd) to display when this child frame window has the input focus....
Definition: frame_window.h:452
int(* get_row)(const TEXT_OBJECT *pThis)
Get the current row cursor for the object.
Definition: text_object.h:422
const char * CHGetHighlightBackgroundColor(Display *pDisplay)
returns highlight background color
Definition: conf_help.c:3425
void(* cursor_up)(TEXT_OBJECT *pThis)
Move the current cursor position up one line.
Definition: text_object.h:605
#define WB_ERROR_PRINT(...)
Preferred method of implementing an 'error level' debug message for all subsystems.
Definition: debug_helper.h:474
int iRowHeight
cached 'row height' (height of line including interline spacing)
Definition: frame_window.h:438
int(* has_select)(const TEXT_OBJECT *pThis)
Returns a non-zero value if there is currently a 'selection'.
Definition: text_object.h:402
void WBFree(void *pBuf)
High performance memory sub-allocator 'free'.
void(* replace_select)(TEXT_OBJECT *pThis, const char *szText, unsigned long cbLen)
Replace the current selection assigned via 'set_select' with new text.
Definition: text_object.h:460
#define IDCANCEL
#define WB_KEYEVENT_SHIFT
'AltCtrlShift' bit flag for Shift modifier for WBKeyEventProcessKey()
void(* set_linefeed)(TEXT_OBJECT *pThis, int iLineFeed)
Set the current linefeed type for the object.
Definition: text_object.h:318
int y
the 'y' value of the point. can be negative.
WB_GEOM geom
total client-area geometry (excludes scroll bars) in 'pixels'
Definition: frame_window.h:433
#define EDIT_WINDOW_TAG
TAG for the WBEditWindow structure.
Definition: edit_window.h:73
INSERT mode, character inserted at cursor.
Definition: text_object.h:168
void FWSetChildFrameScrollInfo(WBChildFrame *pChildFrame, int iRow, int iMaxRow, int iCol, int iMaxCol, int iRowHeight, int iColWidth)
Set the X,Y extent for the child frame (notifies everything)
Definition: child_frame.c:804
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
void(* destructor)(struct tagWBChildFrame *)
pointer to a 'superclass' destructor. If not NULL, will be called by FWDestroyChildFrame()
Definition: frame_window.h:459
Atom WBGetAtom(Display *pDisplay, const char *szAtomName)
Lookup and/or allocate an internal Atom for a named string (lookups include X11 atoms)
#define WB_KEYEVENT_ACSMASK
'AltCtrlShift' bit mask for Alt+Ctrl+Shift bits for WBKeyEventProcessKey()
void(* scroll_vertical)(TEXT_OBJECT *pThis, int nRows)
Scroll the viewport up/down by the specified number of rows.
Definition: text_object.h:666
int(* WBWinEvent)(Window wID, XEvent *pEvent)
event callback function type for window events
void(* del_chars)(TEXT_OBJECT *pThis, int nChar)
Delete 'n' characters from the current cursor. Negative deletes BEFORE the cursor....
Definition: text_object.h:467
void(* end_mouse_drag)(TEXT_OBJECT *pThis)
End a mouse 'drag' operation.
Definition: text_object.h:598
main controlling structure for frame windows
Definition: frame_window.h:274
unsigned int height
internal wrapper struct for 'rectangle' definition
int WBFontDescent(WB_FONTC pFont0)
Get the maximum character descent from a WB_FONT.
Definition: font_helper.c:443
void(* set_row)(TEXT_OBJECT *pThis, int iRow)
Set the current row cursor for the object.
Definition: text_object.h:429
Atom aQUERY_CLOSE
query if it's ok to close (and optionally destroy yourself if ok) a window
WBFrameWindow * pOwner
a pointer to the WBFrameWindow owner
Definition: frame_window.h:430
Display * WBGetWindowDisplay(Window wID)
returns the Display associated with a window
Atom aCONTROL_NOTIFY
dialog control and child window notification messages
void(* cursor_end)(TEXT_OBJECT *pThis)
Move the cursor to 'end' (full doc width or EOL)
Definition: text_object.h:650
static __inline__ WBDialogWindow * DLGGetDialogWindowStruct(Window wID)
Returns a pointer to the dialog window's WBDialogWindow structure.
Atom aEW_HOVER_NOTIFY
Hover notification to user-callback, sent via ClientMessage event.
Definition: edit_window.c:192
void(* cursor_bottom)(TEXT_OBJECT *pThis)
Move the cursor to the last line.
Definition: text_object.h:660
WBEditWindow * WBEditWindowFromWindowID(Window wID)
Obtain the associated WBEditWindow structure pointer for a Window ID.
Definition: edit_window.c:432
int iColWidth
cached 'column width' (width of 1 character)
Definition: frame_window.h:439
void(* ins_chars)(TEXT_OBJECT *pThis, const char *pChar, int nChar)
Insert 'n' characters (including new lines) from the current cursor.
Definition: text_object.h:483
const char * CHGetBackgroundColor(Display *pDisplay)
returns background color for non-static elements
Definition: conf_help.c:3341
void(* cursor_left)(TEXT_OBJECT *pThis)
Move the current cursor position left one column.
Definition: text_object.h:615
TEXT_OBJECT xTextObject
the 'TEXT_OBJECT' member, that does MOST of the work
Definition: edit_window.h:174
Window wIDOwner
owner window (cached from paint/expose handling and/or cursor blink)
Definition: text_object.h:898
Atom aBUTTON_PRESS
CONTROL_NOTIFY ClientMessage for BUTTON_PRESS event.
int WBSetBackground(WBGC hGC, unsigned long background)
Assign background color, a wrapper for XSetBackground()
void WBDebugPrint(const char *pFmt,...) __attribute__((format(printf
conditional debug message output
Atom aWB_TIMER
timer notifications generated by API
default for OS
Definition: text_object.h:139
unsigned long long llModDateTime
file's mod date/time - see WBGetFileModDateTime()
Definition: edit_window.h:167
#define WB_KEYEVENT_CTRL
'AltCtrlShift' bit flag for Control modifier for WBKeyEventProcessKey()
Visibility flag.
An allocated structure containing XFontStruct, XFontInfo, and XftFont [as applicable] for a specified...
Definition: font_helper.h:152
void(* page_left)(TEXT_OBJECT *pThis)
Move the current cursor position left one page.
Definition: text_object.h:635
void(* cursor_blink)(TEXT_OBJECT *pThis, int bHasFocus)
Periodic callback to 'blink' the cursor.
Definition: text_object.h:722
int CreateTimer(Display *pDisplay, Window wID, unsigned long lInterval, long lID, int iPeriodic)
Creates a one-shot or periodic timer.
void WBEndModal(Window wID, int iRval)
End a modal window with a specific return value.
char * WBCopyString(const char *pSrc)
A simple utility that returns a WBAlloc() copy of a 0-byte terminated string.
int WBEditWindowSaveFile(WBEditWindow *pEditWindow, const char *pszFileName)
Save the contents from the Edit Window to a file, overwriting the file if it already exists.
Definition: edit_window.c:538
void WBDestroyEditWindow(WBEditWindow *pEditWindow)
Destroy an Edit Window.
Definition: edit_window.c:390
unsigned int height
the 'height' value of the extent.
internal wrapper struct for 'point' definition
void * WBGetClipboardData(Display *pDisplay, Atom *paType, int *piFormat, unsigned long *pnData)
Get clipboard data of requested type.
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
Atom aRESIZE_NOTIFY
notification of window re-size via ClientMessage
void WBEditWindowClear(WBEditWindow *pEditWindow)
Clear the contents in the Edit Window, and NULL the stored file name.
Definition: edit_window.c:564
static __inline__ void WBDestroyInPlaceTextObject(TEXT_OBJECT *pTextObject)
Destroy a previously initialized 'in-place' TEXT_OBJECT structure.
Definition: text_object.h:1070
static __inline__ int WBIsValidEditWindow(WBEditWindow *pEditWindow)
Check for valid WBEditWindow pointer.
Definition: edit_window.h:281
Structure that defines a Child Frame's UI, mainly for a 'superclass'.
Definition: frame_window.h:677
void(* begin_highlight)(TEXT_OBJECT *pThis)
Begin a highlight block.
Definition: text_object.h:552
Window wID
window ID of the dialog (frame) window
const char * WB_PCSTR
pointer to const char string - a convenience typedef
int(* get_cols)(TEXT_OBJECT *pThis)
Call this function to obtain the estimated column extent of the document.
Definition: text_object.h:282
void(* cursor_top)(TEXT_OBJECT *pThis)
Move the cursor to the top line.
Definition: text_object.h:655
Atom aSTRING
STRING Atom for the clipboard - uses XA_STRING.
#define WB_WARN_PRINT(...)
Preferred method of implementing a 'warning level' debug message for all subsystems.
Definition: debug_helper.h:467
void(* cursor_down)(TEXT_OBJECT *pThis)
Move the current cursor position down one line.
Definition: text_object.h:610
struct tagWBChildFrameUI * pUI
pointer to 'WBChildFrameUI' function pointer table (assigned by 'superclass')
Definition: frame_window.h:460
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
Atom aUTF8_STRING
UTF8_STRING Atom for the clipboard.
WB_FONT pFont
default font for the window
Definition: frame_window.h:431
WBGC WBBeginPaintGeom(Window wID, WB_GEOM *pgBounds)
'Paint' helper, creates a WBGC for use in updating the window for a specified rectangular area
void(* scroll_horizontal)(TEXT_OBJECT *pThis, int nCols)
Scroll the cursor to the right/left a specified number of columns.
Definition: text_object.h:672