X11workbench Toolkit  1.0
dialog_support.c
1 // _ _ _ _ //
3 // __| |(_) __ _ | | ___ __ _ ___ _ _ _ __ _ __ ___ _ __ | |_ ___ //
4 // / _` || | / _` || | / _ \ / _` | / __|| | | || '_ \ | '_ \ / _ \ | '__|| __| / __| //
5 // | (_| || || (_| || || (_) || (_| | \__ \| |_| || |_) || |_) || (_) || | | |_ _| (__ //
6 // \__,_||_| \__,_||_| \___/ \__, |_____|___/ \__,_|| .__/ | .__/ \___/ |_| \__|(_)\___| //
7 // |___/|_____| |_| |_| //
8 // //
9 // //
10 // additional dialog control support //
11 // This file contains various support and functionality that is common to dialog controls //
12 // //
14 
15 
16 /*****************************************************************************
17 
18  X11workbench - X11 programmer's 'work bench' application and toolkit
19  Copyright (c) 2010-2018 by Bob Frazier (aka 'Big Bad Bombastic Bob')
20  all rights reserved
21 
22  DISCLAIMER: The X11workbench application and toolkit software are supplied
23  'as-is', with no warranties, either implied or explicit.
24  Any claims to alleged functionality or features should be
25  considered 'preliminary', and might not function as advertised.
26 
27  BSD-like license:
28 
29  There is no restriction as to what you can do with this software, so long
30  as you include the above copyright notice and DISCLAIMER for any distributed
31  work that is equal to or derived from this one, along with this paragraph
32  that explains the terms of the license if the source is also being made
33  available. A "derived work" describes a work that uses a significant portion
34  of the source files or algorithms that are included with this one.
35  Specifically excluded from this are files that were generated by the software,
36  or anything that is included with the software that is part of another package
37  (such as files that were created or added during the 'configure' process).
38  Specifically included is the use of part or all of any of the X11 workbench
39  toolkit source or header files in your distributed application. If you do not
40  ship the source, the above copyright statement is still required to be placed
41  in a reasonably prominent place, such as documentation, splash screens, and/or
42  'about the application' dialog boxes.
43 
44  Use and distribution are in accordance with GPL, LGPL, and/or the above
45  BSD-like license. See COPYING and README files for more information.
46 
47 
48  Additional information at http://sourceforge.net/projects/X11workbench
49 
50 ******************************************************************************/
51 
52 
53 #ifdef linux /* needed for debian, possibly others */
54 #define _GNU_SOURCE /* in case features.h is involved on linux */
55 #define __USE_GNU /* this enables a few more things in the headers like 'qsort_r' */
56 // TODO: consider making this a 'configure' thing
57 #endif // linux
58 
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <unistd.h>
62 #include <memory.h>
63 #include <string.h>
64 #include <strings.h>
65 #include <signal.h>
66 #include <time.h>
67 #include <sys/stat.h>
68 
69 #ifndef XK_Delete /* moslty for interix */
70 #define XK_MISCELLANY /* mostly for interix */
71 #include <X11/keysymdef.h> // some platforms don't automatically include this with X headers
72 #endif // XK_Delete
73 
74 #define DIALOG_SUPPORT_C /* prevents me from including the various Atom definitions */
75 
76 #include "window_helper.h"
77 #include "pixmap_helper.h" // pixmap helpers, including pre-defined icons
78 #include "dialog_window.h"
79 #include "dialog_controls.h"
80 #include "dialog_support.h" // internal-only definitions
81 #include "conf_help.h"
82 #include "file_help.h"
83 #include "draw_text.h"
84 #include "text_object.h"
85 #include "window_dressing.h"
86 
89 #define THIS_SUBSYSTEM DebugSubSystem_DialogCtrl
90 
91 
92 
93 
94 #define INIT_ATOM(X) if(a##X == None){ a##X = WBGetAtom(WBGetDefaultDisplay(),X##_STR); }
95 #define INIT_ATOM2(X,Y) if(X == None){ X = WBGetAtom(WBGetDefaultDisplay(),Y); }
96 
97 #define DEFAULT_LISTINFO_MAX 16384 /* default initial max # of items in LISTINFO */
98 
99 
100 
101 // atoms first
102 // TODO: make this documentation a bit better. for now the format is OK in doxygen, a little flakey here
103 
106 Atom aFRAME_CONTROL = None;
107 
109 Atom aTEXT_CONTROL = None;
110 
112 Atom aICON_CONTROL = None;
113 
115 Atom aIMAGE_CONTROL = None;
116 
118 Atom aEDIT_CONTROL = None;
119 
121 Atom aPUSHBUTTON_CONTROL = None;
122 
125 
128 
130 Atom aRADIOBUTTON_CONTROL = None;
131 
134 
136 Atom aCHECKBUTTON_CONTROL = None;
137 
140 
142 Atom aHSCROLL_CONTROL = None;
143 
145 Atom aVSCROLL_CONTROL = None;
146 
148 Atom aSLIDER_CONTROL = None;
149 
151 Atom aKNOB_CONTROL = None;
152 
154 Atom aLIST_CONTROL = None;
155 
157 Atom aCOMBO_CONTROL = None;
158 
160 Atom aTREE_CONTROL = None;
161 
163 Atom aCOMBOTREE_CONTROL = None;
164 
166 Atom aFILE_LIST_CONTROL = None;
167 
169 Atom aFILE_COMBO_CONTROL = None;
170 
172 Atom aPATH_TREE_CONTROL = None;
173 
175 Atom aTAB_CONTROL = None;
176 
177 
178 // NOTE: 'xatoms' is in the CORE group - consider moving this into CORE
179 
180 
181 
183 
195 Atom aBUTTON_PRESS = None;
209 Atom aLIST_NOTIFY = None;
222 Atom aTEXT_CHANGED = None;
237 Atom aTEXTSELECT_CHANGE = None;
250 Atom aGOTFOCUS = None;
263 Atom aLOSTFOCUS = None;
278 Atom aMOUSE_CLICK = None;
293 Atom aMOUSE_DBLCLICK = None;
308 Atom aMOUSE_DRAG = None;
321 Atom aKEY_DOWN = None;
334 Atom aKEY_UP = None;
347 Atom aKEYSTROKE = None;
348 
358 Atom aDIALOG_INIT = None;
359 
370 Atom aDLGC_PROP_NOTIFY = None;
371 
383 Atom aLIST_SELCHANGE = None; // list selection has changed (send to self)
384 
385 // control command messages sent to controls to set/get info
399 Atom aDLGC_CONTROL_SET = None;
400 
417 Atom aDLGC_CONTROL_GET = None;
418 
419 // internal-only properties (still have global scope for inline functions, etc.)
426 Atom aDLGC_TEXT = None; // dialog control 'text' property, i.e. 'GetText'
431 Atom aDLGC_CAPTION = None; // dialog control 'caption' property, i.e. 'GetCaption' (not an actual property, notification only)
438 Atom aDLGC_FONT = None;
447 Atom aDLGC_SCROLLINFO = None; // scrollbar info structure (horizontal AND vertical)
448  // (scrollbars, listboxes, combo boxes, multi-line edit)
457 Atom aDLGC_LISTINFO = None; // listbox info structure
458 
468 Atom aDLGC_PATH = None;
469 
470 
472 {
473  INIT_ATOM(FRAME_CONTROL);
474  INIT_ATOM(TEXT_CONTROL);
475  INIT_ATOM(ICON_CONTROL);
476  INIT_ATOM(IMAGE_CONTROL);
477  INIT_ATOM(EDIT_CONTROL);
478  INIT_ATOM(PUSHBUTTON_CONTROL);
479  INIT_ATOM(DEFPUSHBUTTON_CONTROL);
480  INIT_ATOM(CANCELBUTTON_CONTROL);
481  INIT_ATOM(RADIOBUTTON_CONTROL);
482  INIT_ATOM(FIRSTRADIOBUTTON_CONTROL);
483  INIT_ATOM(CHECKBUTTON_CONTROL);
484  INIT_ATOM(TRISTATEBUTTON_CONTROL);
485  INIT_ATOM(HSCROLL_CONTROL);
486  INIT_ATOM(VSCROLL_CONTROL);
487  INIT_ATOM(SLIDER_CONTROL);
488  INIT_ATOM(KNOB_CONTROL);
489  INIT_ATOM(LIST_CONTROL);
490  INIT_ATOM(COMBO_CONTROL);
491  INIT_ATOM(TREE_CONTROL);
492  INIT_ATOM(COMBOTREE_CONTROL);
493  INIT_ATOM(FILE_LIST_CONTROL);
494  INIT_ATOM(FILE_COMBO_CONTROL);
495  INIT_ATOM(PATH_TREE_CONTROL);
496  INIT_ATOM(TAB_CONTROL);
497 
498 // INIT_ATOM2(aCONTROL_NOTIFY,"ControlNotify");
499  INIT_ATOM2(aBUTTON_PRESS,"ButtonPress");
500  INIT_ATOM2(aLIST_NOTIFY,"ListNotify");
501  INIT_ATOM2(aTEXT_CHANGED,"TextChanged");
502  INIT_ATOM2(aTEXTSELECT_CHANGE,"TextSelectChange");
503  INIT_ATOM2(aGOTFOCUS,"GotFocus");
504  INIT_ATOM2(aLOSTFOCUS,"LostFocus");
505  INIT_ATOM2(aMOUSE_CLICK,"MouseDown");
506  INIT_ATOM2(aMOUSE_DBLCLICK,"MouseUp");
507  INIT_ATOM2(aMOUSE_DRAG,"MouseDrag");
508  INIT_ATOM2(aKEY_DOWN,"KeyDown");
509  INIT_ATOM2(aKEY_UP,"KeyUp");
510  INIT_ATOM2(aKEYSTROKE,"Keystroke");
511 
512  INIT_ATOM2(aDLGC_CONTROL_SET,"DLGC_CONTROL_SET");
513  INIT_ATOM2(aDLGC_CONTROL_GET,"DLGC_CONTROL_GET");
514 
515  INIT_ATOM2(aDLGC_TEXT, "DLGC_TEXT");
516  INIT_ATOM2(aDLGC_CAPTION, "DLGC_CAPTION");
517  INIT_ATOM2(aDLGC_FONT, "DLGC_FONT");
518  INIT_ATOM2(aDLGC_SCROLLINFO, "DLGC_SCROLLINFO");
519  INIT_ATOM2(aDLGC_LISTINFO, "DLGC_LISTINFO");
520  INIT_ATOM2(aDLGC_PATH, "DLGC_PATH");
521 
522 
523  // other dialog-related messages
524  INIT_ATOM2(aDIALOG_INIT,"DialogInit");
525 // INIT_ATOM2(aDIALOG_SETFOCUS,"DialogSetFocus");
526  INIT_ATOM2(aDLGC_PROP_NOTIFY, "DLGCPropNotify");
527  INIT_ATOM2(aLIST_SELCHANGE, "LIST_SELCHANGE");
528 
529 }
530 
531 
533 // D I A L O G C O N T R O L P R O P E R T I E S
535 
536 
537 void WBDialogControlSetCaption(WBDialogControl *pCtrl, const char *szCaption)
538 {
539 char *szOldCaption = pCtrl->pCaption;
540 
541  pCtrl->pCaption = WBCopyString(szCaption);
542 
543  if(szOldCaption)
544  {
545  WBFree(szOldCaption);
546  }
547 
548  WBInvalidateGeom(pCtrl->wID, NULL, 0);
549  WBUpdateWindow(pCtrl->wID); // schedule update (not immediate)
550 
551  DLGNotifySelf(pCtrl, aDLGC_PROP_NOTIFY, aDLGC_CAPTION, 0, 0, 0, 0);
552 }
553 
555 {
556  if(!pCtrl->pCaption)
557  {
558  return "";
559  }
560 
561  return pCtrl->pCaption;
562 }
563 
564 void WBDialogControlSetPixmap(WBDialogControl *pCtrl, Pixmap pixmap)
565 {
566 Display *pDisplay = NULL;
567 
568  if(!pCtrl ||
569  (pCtrl->aClass != aICON_CONTROL && pCtrl->aClass != aIMAGE_CONTROL
570  && pCtrl->aClass != aPUSHBUTTON_CONTROL && pCtrl->aClass != aDEFPUSHBUTTON_CONTROL
571  && pCtrl->aClass != aCANCELBUTTON_CONTROL))
572  {
573  return;
574  }
575 
576  pDisplay = WBGetWindowDisplay(pCtrl->wID);
577 
578  if(!pDisplay)
579  {
580  pDisplay = WBGetDefaultDisplay();
581  }
582 
583  if(pCtrl->aClass == aICON_CONTROL ||
584  pCtrl->aClass == aIMAGE_CONTROL)
585  {
586  Pixmap pxOld = ((struct _WB_IMAGE_CONTROL_ *)pCtrl)->pixmap;
587  Pixmap pxOld2 = ((struct _WB_IMAGE_CONTROL_ *)pCtrl)->pixmap2;
588 
589  ((struct _WB_IMAGE_CONTROL_ *)pCtrl)->pixmap = pixmap;
590  ((struct _WB_IMAGE_CONTROL_ *)pCtrl)->pixmap2 = None;
591 
593  if(pxOld != None)
594  {
595  XFreePixmap(pDisplay, pxOld);
596  }
597  if(pxOld2 != None)
598  {
599  XFreePixmap(pDisplay, pxOld2);
600  }
602  }
603 
604  if(pCtrl->aClass == aPUSHBUTTON_CONTROL || pCtrl->aClass == aDEFPUSHBUTTON_CONTROL
605  || pCtrl->aClass == aCANCELBUTTON_CONTROL)
606  {
607  Pixmap pxOld = ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap;
608  Pixmap pxOld2 = ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap2;
609 
610  ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap = pixmap;
611  ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap2 = None;
612 
614  if(pxOld != None)
615  {
616  XFreePixmap(pDisplay, pxOld);
617  }
618  if(pxOld2 != None)
619  {
620  XFreePixmap(pDisplay, pxOld2);
621  }
623  }
624 }
625 
627 {
628  if(!pCtrl)
629  {
630  return None;
631  }
632 
633  if(pCtrl->aClass == aICON_CONTROL ||
634  pCtrl->aClass == aIMAGE_CONTROL)
635  {
636  return ((struct _WB_IMAGE_CONTROL_ *)pCtrl)->pixmap;
637  }
638 
639  if(pCtrl->aClass == aPUSHBUTTON_CONTROL || pCtrl->aClass == aDEFPUSHBUTTON_CONTROL
640  || pCtrl->aClass == aCANCELBUTTON_CONTROL)
641  {
642  return ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap;
643  }
644 
645  return None;
646 }
647 
649 {
650 Display *pDisplay = NULL;
651 
652  if(!pCtrl ||
653  (pCtrl->aClass != aICON_CONTROL && pCtrl->aClass != aIMAGE_CONTROL
654  && pCtrl->aClass != aPUSHBUTTON_CONTROL && pCtrl->aClass != aDEFPUSHBUTTON_CONTROL
655  && pCtrl->aClass != aCANCELBUTTON_CONTROL))
656  {
657  return;
658  }
659 
660  pDisplay = WBGetWindowDisplay(pCtrl->wID);
661 
662  if(!pDisplay)
663  {
664  pDisplay = WBGetDefaultDisplay();
665  }
666 
667  if(pCtrl->aClass == aICON_CONTROL ||
668  pCtrl->aClass == aIMAGE_CONTROL)
669  {
670  Pixmap pxOld = ((struct _WB_IMAGE_CONTROL_ *)pCtrl)->pixmap;
671  Pixmap pxOld2 = ((struct _WB_IMAGE_CONTROL_ *)pCtrl)->pixmap2;
672 
673  ((struct _WB_IMAGE_CONTROL_ *)pCtrl)->pixmap = pixmap;
674  ((struct _WB_IMAGE_CONTROL_ *)pCtrl)->pixmap2 = pixmap2;
675 
677  if(pxOld != None)
678  {
679  XFreePixmap(pDisplay, pxOld);
680  }
681  if(pxOld2 != None)
682  {
683  XFreePixmap(pDisplay, pxOld2);
684  }
686  }
687 
688  if(pCtrl->aClass == aPUSHBUTTON_CONTROL || pCtrl->aClass == aDEFPUSHBUTTON_CONTROL
689  || pCtrl->aClass == aCANCELBUTTON_CONTROL)
690  {
691  Pixmap pxOld = ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap;
692  Pixmap pxOld2 = ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap2;
693 
694  ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap = pixmap;
695  ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap2 = pixmap2;
696 
698  if(pxOld != None)
699  {
700  XFreePixmap(pDisplay, pxOld);
701  }
702  if(pxOld2 != None)
703  {
704  XFreePixmap(pDisplay, pxOld2);
705  }
707  }
708 }
709 
710 Pixmap WBDialogControlGetIconPixmap(WBDialogControl *pCtrl, Pixmap *pPixmap2)
711 {
712  if(!pCtrl)
713  {
714  return None;
715  }
716 
717  if(pCtrl->aClass == aICON_CONTROL ||
718  pCtrl->aClass == aIMAGE_CONTROL)
719  {
720  if(pPixmap2)
721  {
722  *pPixmap2 = ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap2;
723  }
724 
725  return ((struct _WB_IMAGE_CONTROL_ *)pCtrl)->pixmap;
726  }
727 
728  if(pCtrl->aClass == aPUSHBUTTON_CONTROL || pCtrl->aClass == aDEFPUSHBUTTON_CONTROL
729  || pCtrl->aClass == aCANCELBUTTON_CONTROL)
730  {
731  if(pPixmap2)
732  {
733  *pPixmap2 = ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap2;
734  }
735 
736  return ((struct _WB_PUSHBUTTON_CONTROL_ *)pCtrl)->pixmap;
737  }
738 
739  return None;
740 }
741 
742 void WBDialogControlSetCheck(WBDialogControl *pCtrl, int iCheck)
743 {
744  if(!pCtrl || pCtrl->wID == None)
745  {
746  return;
747  }
748 
749  XClientMessageEvent evt = {
750  .type=ClientMessage,
751  .serial=0,
752  .send_event=0,
753  .display=WBGetWindowDisplay(pCtrl->wID),
754  .window=pCtrl->wID,
755  .message_type=aDLGC_CONTROL_SET,
756  .format=32
757  };
758 
759  evt.data.l[0] = ControlGetSet_CHECK;
760  evt.data.l[1] = iCheck;
761 
762  WBWindowDispatch(pCtrl->wID, (XEvent *)&evt); // call the window proc immediately to process it
763 }
764 
766 {
767  if(!pCtrl || pCtrl->wID == None)
768  {
769  return 0;
770  }
771 
772  XClientMessageEvent evt = {
773  .type=ClientMessage,
774  .serial=0,
775  .send_event=0,
776  .display=WBGetWindowDisplay(pCtrl->wID),
777  .window=pCtrl->wID,
778  .message_type=aDLGC_CONTROL_GET,
779  .format=32
780  };
781 
782  evt.data.l[0] = ControlGetSet_CHECK;
783 
784  return WBWindowDispatch(pCtrl->wID, (XEvent *)&evt); // call the window proc immediately to process it
785 }
786 
787 
788 int WBDialogControlSetPropList(WBDialogControl *pCtrl, const char *szPropList)
789 {
790 // property<tab>value<newline>
791 
792  return 0; // for now (not being used yet)
793 }
794 
795 int WBDialogControlSetProperty(WBDialogControl *pCtrl, Atom aPropName, const char *szPropVal)
796 {
797  WB_DIALOG_PROP p;
798 
799  p.aProp = aPropName;
800  p.lVal = 0;
801  p.pVal = WBCopyString(szPropVal);
802 
803  if(!p.pVal)
804  {
805  return -1;
806  }
807 
808  WBDialogControlSetDialogProp(pCtrl, &p);
809  return 0;
810 }
811 
812 void WBDialogControlSetProperty2(WBDialogControl *pCtrl, Atom aPropName, void *pPropVal)
813 {
814  WB_DIALOG_PROP p;
815 
816  p.aProp = aPropName;
817  p.lVal = 0;
818  p.pVal = pPropVal;
819 
820  WBDialogControlSetDialogProp(pCtrl, &p);
821 }
822 
823 const char *WBDialogControlGetProperty(WBDialogControl *pCtrl, Atom aPropName)
824 {
825 const WB_DIALOG_PROP *pP = WBDialogControlGetDialogProp(pCtrl, aPropName);
826 
827  if(pP)
828  {
829  return pP->pVal; // TODO: if NULL, lVal as a string?
830  }
831 
832  return ""; // so it's not NULL
833 }
834 
835 void *WBDialogControlGetProperty2(WBDialogControl *pCtrl, Atom aPropName)
836 {
837 const WB_DIALOG_PROP *pP = WBDialogControlGetDialogProp(pCtrl, aPropName);
838 
839  if(pP)
840  {
841  return (void *)(pP->pVal); // TODO: if NULL, lVal as a string?
842  }
843 
844  return NULL;
845 }
846 
847 
848 
849 #define INITIAL_PROPERTY_MAX 64
850 
851 static WBDialogPropList * __ConstructPropList(void)
852 {
853  int iInitialSize = sizeof(WBDialogPropList) + INITIAL_PROPERTY_MAX * sizeof(WB_DIALOG_PROP);
854  WBDialogPropList *pRval = (WBDialogPropList *)WBAlloc(iInitialSize);
855 
856  if(pRval)
857  {
858  pRval->nProps = 0;
859  pRval->nMaxProps = INITIAL_PROPERTY_MAX;
860  WB_WARN_PRINT("TEMPORARY: WBDialogPropList constructor %p %d, %d\n", pRval, pRval->nProps, pRval->nMaxProps);
861  }
862  else
863  {
864  WB_ERROR_PRINT("%s - not enough memory\n", __FUNCTION__);
865  }
866 
867  return pRval;
868 }
869 
871 {
872 int i1;
873 WBDialogPropList *pPropList;
874 WB_DIALOG_PROP *pProp = NULL;
875 Atom aProp;
876 
877  if(!pCtrl || !pPropVal)
878  {
879  WB_ERROR_PRINT("%s - pCtrl %p or pPropVal %p\n", __FUNCTION__,
880  pCtrl, pPropVal);
881 
882  return -1;
883  }
884 
885  if(!pCtrl->pPropList)
886  {
887  if(!(pCtrl->pPropList = __ConstructPropList()))
888  {
889  WB_ERROR_PRINT("%s - unable to allocate property list for window %d (%08xH)\n",
890  __FUNCTION__, (int)pCtrl->wID, (int)pCtrl->wID);
891 
892  return -2;
893  }
894  }
895 
896  pPropList = pCtrl->pPropList;
897  aProp = pPropVal->aProp;
898 
899  for(i1=0; i1 < pPropList->nProps; i1++)
900  {
901  register WB_DIALOG_PROP *pProp0 = &(pPropList->aDlgProp[i1]);
902 
903  if(pProp0 && pProp0->aProp == aProp)
904  {
905  pProp = pProp0;
906  break;
907  }
908  }
909 
910  if(!pProp)
911  {
912  if((pPropList->nProps + 1) >= pPropList->nMaxProps)
913  {
914  int iNewSize = (pPropList->nMaxProps + INITIAL_PROPERTY_MAX / 2)
915  * sizeof(pPropList->aDlgProp[0])
916  + sizeof(*pPropList);
917 
918  pPropList = (WBDialogPropList *)WBReAlloc(pPropList, iNewSize);
919  if(!pPropList)
920  {
921  WB_ERROR_PRINT("%s - unable to RE-allocate property list for window %d (%08xH)\n",
922  __FUNCTION__, (int)pCtrl->wID, (int)pCtrl->wID);
923 
924  return -3;
925  }
926 
927  pCtrl->pPropList = pPropList;
928  pPropList->nMaxProps += INITIAL_PROPERTY_MAX / 2;
929 
930  if(pPropList->nProps >= pPropList->nMaxProps)
931  {
932  WB_ERROR_PRINT("%s - internal inconsistency, nProps=%d, nMaxProps=%d\n",
933  __FUNCTION__, pPropList->nProps, pPropList->nMaxProps);
934  return -4;
935  }
936  }
937 
938  pProp = &(pPropList->aDlgProp[pPropList->nProps]);
939  pPropList->nProps++;
940 
941  pProp->aProp = aProp;
942  pProp->lVal = 0;
943  pProp->pVal = NULL;
944  }
945 
946  pProp->lVal = pPropVal->lVal; // just copy the lVal
947 
948  if(pProp->pVal != pPropVal->pVal) // if it changes... and ONLY if it changes
949  {
950  if(pProp->pVal)
951  {
952  if(pProp->aProp == aDLGC_LISTINFO)
953  {
954  DLGCListInfoDestructor((LISTINFO *)(pProp->pVal));
955  }
956  else
957  {
958  WBFree(pProp->pVal);
959  }
960  }
961 
962  pProp->pVal = pPropVal->pVal;
963  }
964 
965  // last but not least, tell the dialog control its properties were altered
966  // by directly calling its callback function with the 'property change' event
967 
968  WB_DEBUG_PRINT(DebugLevel_Chatty | DebugSubSystem_DialogCtrl | DebugSubSystem_Dialog,
969  "%s - DLGC_PROP_NOTIFY (set) for window %d (%08xH)\n",
970  __FUNCTION__, (int)pCtrl->wID, (int)pCtrl->wID);
971 
972  DLGNotifySelf(pCtrl, aDLGC_PROP_NOTIFY, pPropVal->aProp, 0, 0, 0, 0);
973 
974  return 0; // success
975 }
976 
978 {
979 int i1, bNotify = 0;
980 WBDialogPropList *pPropList = pCtrl ? pCtrl->pPropList : NULL;
981 //WB_DIALOG_PROP *pProp2 = NULL;
982 WB_DIALOG_PROP sProp;
983 
984 
985  if(!pPropList)
986  {
987  return;
988  }
989 
990  for(i1=0; i1 < pPropList->nProps; i1++)
991  {
992  register WB_DIALOG_PROP *pProp = &(pPropList->aDlgProp[i1]);
993 
994  if(pProp && pProp->aProp == aProp)
995  {
996  if(pProp->pVal) // pointer?
997  {
998  if(pProp->aProp == aDLGC_LISTINFO)
999  {
1000  DLGCListInfoDestructor((LISTINFO *)(pProp->pVal));
1001  }
1002  else
1003  {
1004  WBFree(pProp->pVal);
1005  }
1006 
1007  pProp->pVal = NULL; // necessary, for the next step
1008  }
1009 
1010  memcpy(&sProp, pProp, sizeof(WB_DIALOG_PROP)); // make a copy of the thing
1011  bNotify = 1;
1012 
1013  // must remove this entry now
1014  for(i1++; i1 < pPropList->nProps; i1++)
1015  {
1016  pPropList->aDlgProp[i1 - 1] = pPropList->aDlgProp[i1];
1017  }
1018 
1019  pPropList->nProps--;
1020  bzero(&(pPropList->aDlgProp[pPropList->nProps]), sizeof(pPropList->aDlgProp[pPropList->nProps]));
1021 
1022  break;
1023  }
1024  }
1025 
1026  // last but not least, tell the dialog control its properties were altered
1027  // by directly calling its callback function with the 'property change' event
1028 
1029 // if(pProp2) NO NO NO! but this is how 'set' does it, since 'pProp2' is still valid
1030 // {
1031 // DLGNotifySelf(pCtrl, aDLGC_PROP_NOTIFY, pProp2->aProp, 0, 0, 0, 0);
1032 // }
1033 
1034  // TODO: find a better way to notify for a property that was deleted.
1035  // for now I copied the prop structure
1036 
1037  if(bNotify)
1038  {
1039  WB_DEBUG_PRINT(DebugLevel_Chatty | DebugSubSystem_DialogCtrl | DebugSubSystem_Dialog,
1040  "%s - DLGC_PROP_NOTIFY (del) for window %d (%08xH)\n",
1041  __FUNCTION__, (int)pCtrl->wID, (int)pCtrl->wID);
1042 
1043  DLGNotifySelf(pCtrl, aDLGC_PROP_NOTIFY, sProp.aProp, 0, 0, 0, 0);
1044  }
1045 
1046 }
1047 
1049 {
1050 int i1;
1051 WBDialogPropList *pPropList = pCtrl ? pCtrl->pPropList : NULL;
1052 
1053  if(!pPropList)
1054  {
1055  return NULL; // for NULL 'pCtrl' will always be the case
1056  }
1057 
1058  for(i1=0; i1 < pPropList->nProps; i1++)
1059  {
1060  register WB_DIALOG_PROP *pProp = &(pPropList->aDlgProp[i1]);
1061 
1062  if(pProp && pProp->aProp == aProp)
1063  {
1064  return pProp;
1065  }
1066  }
1067 
1068  return NULL; // not found
1069 }
1070 
1072 {
1073 int i1;
1074 
1075  if(!pPropList)
1076  {
1077  return;
1078  }
1079 
1080  for(i1=0; i1 < pPropList->nProps; i1++)
1081  {
1082  /*register*/ WB_DIALOG_PROP *pProp = &(pPropList->aDlgProp[i1]);
1083 
1084  if(pProp->pVal) // pointer?
1085  {
1086  if(pProp->aProp == aDLGC_LISTINFO)
1087  {
1088  DLGCListInfoDestructor((LISTINFO *)(pProp->pVal));
1089  }
1090  else
1091  {
1092  WBFree(pProp->pVal);
1093  }
1094 
1095 #if 0
1096  { // debug code to prevent re-free problems with b0rked list
1097  int i2;
1098 
1099  for(i2=i1+1; i2 < pPropList->nProps; i2++)
1100  {
1101  register WB_DIALOG_PROP *pProp2 = &(pPropList->aDlgProp[i2]);
1102 
1103  if(pProp->pVal == pProp2->pVal)
1104  {
1105  if(pProp->aProp == pProp2->aProp)
1106  {
1107  WB_DEBUG_PRINT(DebugLevel_ERROR | DebugSubSystem_DialogCtrl | DebugSubSystem_Dialog,
1108  "%s - %d %d matching property name %d and value %p detected\n",
1109  __FUNCTION__, i1, i2, (int)(pProp->aProp), pProp->pVal);
1110  }
1111 
1112  pProp2->pVal = NULL;
1113  pProp2->aProp = 0; // for now set this to zero as well
1114  }
1115  }
1116  }
1117 #endif // 0
1118  }
1119 
1120  bzero(pProp, sizeof(*pProp)); // zero out whatever used to be there (as a matter of course)
1121  }
1122 
1123  pPropList->nProps = 0; // matter of course
1124 
1125  WBFree(pPropList); // caller must ensure no duplicate destruction happens
1126 }
1127 
1128 
1129 
1131 // L I S T I N F O H A N D L E R S
1133 
1134 void * DLGCDefaultListInfoAllocator(const void *pData, int cbData)
1135 {
1136  void *pRval;
1137 
1138  if(cbData < 0)
1139  {
1140  if(pData)
1141  {
1142  cbData = strlen((const char *)pData) + 1;
1143  }
1144  else
1145  {
1146  return NULL;
1147  }
1148  }
1149 
1150  pRval = WBAlloc(cbData + 1);
1151 
1152  if(pRval)
1153  {
1154  if(cbData)
1155  {
1156  if(pData)
1157  {
1158  memcpy(pRval, pData, cbData);
1159  }
1160  else
1161  {
1162  bzero(pRval, cbData);
1163  }
1164  }
1165 
1166  ((char *)pRval)[cbData] = 0; // there will always be at least that one extra byte for the zero
1167  }
1168 
1169  return pRval;
1170 }
1171 
1173  void *(*pfnAllocator)(const void *,int), void (*pfnDestructor)(void *),
1174  void (*pfnDisplay)(WBDialogControl *, void *, int, GC, WB_GEOM *, XFontSet),
1175  int (*pfnSort)(const void *, const void *))
1176 {
1177 WB_DIALOG_PROP propTemp;
1178 int i1;
1179 
1180  if(!pfnDisplay)
1181  {
1182  pfnDisplay = DLGCDefaultListControlDisplayProc;
1183  }
1184 
1185  propTemp.aProp = aDLGC_LISTINFO;
1186  propTemp.lVal = 0;
1187  propTemp.pVal = DLGCListInfoConstructor(pCtrl->wID, DEFAULT_LISTINFO_MAX, nFlags,
1188  pfnAllocator, pfnDestructor, pfnDisplay, NULL);
1189 
1190  if(!propTemp.pVal)
1191  {
1192  WB_ERROR_PRINT("%s - DLGCListInfoConstructor returns NULL\n", __FUNCTION__);
1193  return -2;
1194  }
1195 
1196  i1 = WBDialogControlSetDialogProp(pCtrl, &propTemp);
1197 
1198  if(i1)
1199  {
1200  WB_ERROR_PRINT("%s - WBDialogControlSetDialogProp returns %d\n", __FUNCTION__, i1);
1201  DLGCListInfoDestructor(propTemp.pVal);
1202  }
1203 
1204  return i1; // 0 means 'success'
1205 }
1206 
1207 int DLGModifyControlListInfo(WBDialogControl *pCtrl, int bFlags, int nFlags,
1208  int bAllocator, void *(*pfnAllocator)(const void *,int),
1209  int bDestructor, void (*pfnDestructor)(void *),
1210  int bDisplay, void (*pfnDisplay)(WBDialogControl *, void *, int, GC, WB_GEOM *, XFontSet),
1211  int bSort, int (*pfnSort)(const void *, const void *))
1212 {
1213 WB_DIALOG_PROP propTemp;
1214 const WB_DIALOG_PROP *pProp;
1215 LISTINFO *pLI;
1216 //int i1;
1217 
1218 
1220 
1221  if(!pProp)
1222  {
1223  // see DLGInitControlListInfoDefault for canonical default values (this should match it actually)
1224 
1225  return DLGInitControlListInfo(pCtrl, bFlags ? nFlags : ListInfoFlags_SORTED,
1226  bAllocator ? pfnAllocator : DLGCDefaultListInfoAllocator,
1227  bDestructor ? pfnDestructor : WBFree,
1228  bDisplay ? pfnDisplay : NULL,
1229  bSort ? pfnSort : NULL);
1230  }
1231 
1232  memcpy(&propTemp, pProp, sizeof(propTemp));
1233 
1234  if(!propTemp.pVal)
1235  {
1236  WB_ERROR_PRINT("%s - DLGCListInfoConstructor returns NULL\n", __FUNCTION__);
1237  return -2;
1238  }
1239 
1240  pLI = (LISTINFO *)propTemp.pVal;
1241 
1242  // assuming it's ok, assign the various information as specified.
1243 
1244  if(bFlags)
1245  {
1246  pLI->nFlags = nFlags;
1247  }
1248 
1249  if(bAllocator)
1250  {
1251  pLI->pfnAllocator = pfnAllocator;
1252  }
1253 
1254  if(bDestructor)
1255  {
1256  pLI->pfnDestructor = pfnDestructor;
1257  }
1258 
1259  if(bDisplay)
1260  {
1261  if(pfnDisplay)
1262  {
1263  pLI->pfnDisplay = pfnDisplay;
1264  }
1265  else
1266  {
1268  }
1269  }
1270 
1271  if(bSort)
1272  {
1273  if(pfnSort)
1274  {
1275  pLI->pfnSort = pfnSort;
1276  }
1277  else
1278  {
1279  pLI->pfnSort = (int (*)(const void *,const void *))strcmp;
1280  }
1281  }
1282 
1283  return 0;
1284 }
1285 
1286 LISTINFO *DLGCListInfoConstructor(Window wOwner, int nMax, int nFlags,
1287  void *(*pfnAllocator)(const void *,int), void (*pfnDestructor)(void *),
1288  void (*pfnDisplay)(WBDialogControl *, void *, int, GC, WB_GEOM *, XFontSet),
1289  int (*pfnSort)(const void *, const void *))
1290 {
1291 LISTINFO *pRval = WBAlloc(sizeof(*pRval) + nMax * sizeof(const void *));
1292 
1293  if(pRval)
1294  {
1295  pRval->nItems = 0;
1296  pRval->nMaxItems = nMax;
1297  pRval->nPos = 0; // current scroll position (initially zero)
1298  pRval->nTop = 0; // index of top item that's visible
1299  pRval->nHeight = 0; // height of viewport in 'items'
1300  pRval->nFlags = nFlags;
1301  pRval->wOwner = wOwner;
1302  pRval->pfnAllocator = pfnAllocator;
1303  pRval->pfnDestructor = pfnDestructor;
1304  if(pfnDisplay)
1305  {
1306  pRval->pfnDisplay = pfnDisplay;
1307  }
1308  else
1309  {
1311  }
1312  if(pfnSort)
1313  {
1314  pRval->pfnSort = pfnSort;
1315  }
1316  else
1317  {
1318  pRval->pfnSort = (int (*)(const void *,const void *))strcmp;
1319  }
1320  }
1321 
1322  return pRval;
1323 }
1324 
1326 {
1327 int i1;
1328 void **paData;
1329 
1330  if(!pListInfo)
1331  {
1332  return;
1333  }
1334 
1335  paData = pListInfo->aItems;
1336 
1337  WB_DEBUG_PRINT(DebugLevel_Verbose | DebugSubSystem_DialogCtrl | DebugSubSystem_Dialog,
1338  "%s - destroying %d items using %p for %p\n",
1339  __FUNCTION__, pListInfo->nItems, pListInfo->pfnDestructor, pListInfo->aItems);
1340 
1341  for(i1=0; i1 < pListInfo->nItems; i1++)
1342  {
1343  WB_DEBUG_PRINT(DebugLevel_Verbose | DebugSubSystem_DialogCtrl | DebugSubSystem_Dialog,
1344  "%s - destroying item %d, value = %p\n",
1345  __FUNCTION__, i1, paData[i1]);
1346 
1347  if(pListInfo->pfnDestructor)
1348  {
1349  pListInfo->pfnDestructor(paData[i1]);
1350  }
1351  else if(paData[i1])
1352  {
1353  WBFree(paData[i1]);
1354  }
1355  }
1356 
1357  WBFree(pListInfo);
1358 }
1359 
1360 //typedef struct __LISTINFO__
1361 //{
1362 // int nItems, nMaxItems; // size/max size of aItems (must re-alloc to increase nMaxItems)
1363 // int nFlags; // flags (sorted, etc.)
1364 // Window wOwner; // owning window [to be notified on change]
1365 // void *(*pfnAllocator)(void *, int); // copy constructor to call for each item that's added
1366 // // typically this will call 'WBAlloc' followed by 'memcpy'
1367 // // if NULL, the caller-supplied pointer is assigned to 'aItems' as-is
1368 // void (*pfnDestructor)(void *); // destructor to call for each item that's removed
1369 // // typically this will point to 'WBFree'
1370 // // if NULL, the caller-supplied pointer is ignored
1371 //
1372 // void (*pfnDisplay)(WBDialogControl *pControl, void *pData, int iSelected, GC gcPaint, WB_GEOM *pGeom);
1373 // // generic function to display contents of item within 'pGeom' using GC
1374 // // typically one of the listbox 'display item' functions
1375 //
1376 // int (*pfnSort)(const void *, const void *); // sort proc (NULL implies strcmp)
1377 //
1378 // void *aItems[1]; // array of item data (remainder of struct)
1379 //} LISTINFO;
1380 
1381 const char * DLGGetControlListText(WBDialogControl *pCtrl, int iIndex)
1382 {
1383  const LISTINFO *pListInfo;
1385 
1386  if(!pProp || !pProp->pVal)
1387  {
1388  return NULL;
1389  }
1390 
1391  pListInfo = (LISTINFO *)(pProp->pVal);
1392 
1393  if(iIndex == ControlListIndex_LAST)
1394  {
1395  iIndex = pListInfo->nItems - 1;
1396  }
1397 
1398  if(iIndex < 0 || iIndex >= pListInfo->nItems)
1399  {
1400  return NULL;
1401  }
1402 
1403  if(!(pListInfo->aItems[iIndex]))
1404  {
1405  return ""; // always a non-NULL return if the item exists
1406  }
1407 
1408  return (const char *)(pListInfo->aItems[iIndex]);
1409 }
1410 
1411 const void * DLGGetControlListData(WBDialogControl *pCtrl, int iIndex)
1412 {
1413  const LISTINFO *pListInfo;
1415 
1416  if(!pProp || !pProp->pVal)
1417  {
1418  return NULL;
1419  }
1420 
1421  pListInfo = (LISTINFO *)(pProp->pVal);
1422 
1423  if(iIndex == ControlListIndex_LAST)
1424  {
1425  iIndex = pListInfo->nItems - 1;
1426  }
1427 
1428  if(iIndex < 0 || iIndex >= pListInfo->nItems)
1429  {
1430  return NULL;
1431  }
1432 
1433  return pListInfo->aItems[iIndex];
1434 }
1435 
1436 static DECLARE_SORT_FUNCTION(_actual_sort_proc,p0,p1,p2)
1437 //static int _actual_sort_proc(void *p0, const void *p1, const void *p2)
1438 {
1439  const void *p1a = *((const void * const *)p1);
1440  const void *p2a = *((const void * const *)p2);
1441  LISTINFO *pListInfo = (LISTINFO *)p0;
1442 
1443  if(pListInfo->pfnSort)
1444  {
1445  return pListInfo->pfnSort(p1a, p2a);
1446  }
1447 
1448  return strcmp(p1a, p2a);
1449 }
1450 
1451 int DLGAddControlListEntry(WBDialogControl *pCtrl, const char *pData, long cbData, int iIndex)
1452 {
1453  LISTINFO *pListInfo, *pListInfo0;
1455  WB_DIALOG_PROP propTemp;
1456  int i1;
1457  void *pTemp;
1458 
1459  if(!pProp || !pProp->pVal)
1460  {
1461  if(!(pCtrl->ulFlags & CONTROL_SupportListInfo))
1462  {
1463  // check first for the property, then return an error if it's
1464  // not supported (you never know...)
1465 
1466  WB_ERROR_PRINT("%s - control does not support 'LISTINFO'\n", __FUNCTION__);
1467  return -3;
1468  }
1469 
1470  pListInfo0 = NULL;
1471 
1472  // use the default settings to initialize the LISTINFO
1473  propTemp.aProp = aDLGC_LISTINFO;
1474  propTemp.lVal = 0;
1475  propTemp.pVal = DLGCListInfoConstructor(pCtrl->wID, DEFAULT_LISTINFO_MAX, ListInfoFlags_SORTED,
1477  WBFree,
1479  NULL);
1480 
1481  if(!propTemp.pVal)
1482  {
1483  WB_ERROR_PRINT("%s - unable to allocate 'LISTINFO'\n", __FUNCTION__);
1484  return -3; // error (unable to allocate LISTINFO)
1485  }
1486  }
1487  else
1488  {
1489  propTemp.aProp = pProp->aProp;
1490  propTemp.lVal = pProp->lVal;
1491  propTemp.pVal = pProp->pVal;
1492 
1493  pListInfo0 = (LISTINFO *)propTemp.pVal;
1494  }
1495 
1496  pListInfo = (LISTINFO *)propTemp.pVal;
1497 
1498  if(iIndex == ControlListIndex_INSERT_FIRST)
1499  {
1500  iIndex = -1; // note - this should really have no effect at all
1501  }
1502  else if(iIndex == ControlListIndex_INSERT_LAST)
1503  {
1504  iIndex = pListInfo->nItems - 1;
1505  }
1506  else if(iIndex < 0 || iIndex >= pListInfo->nItems)
1507  {
1508  if(!pListInfo0)
1509  {
1510  DLGCListInfoDestructor(propTemp.pVal);
1511  }
1512 
1513  WB_ERROR_PRINT("%s - invalid index %d\n", __FUNCTION__, iIndex);
1514 
1515  return -2;
1516  }
1517 
1518  if((iIndex + 1) >= pListInfo->nMaxItems)
1519  {
1520  int nItems = pListInfo->nMaxItems;
1521  // time to re-allocate
1522 
1523  if(nItems <= 0x40000)
1524  {
1525  nItems *= 2;
1526  }
1527  else
1528  {
1529  nItems += 0x40000;
1530  }
1531 
1532  i1 = sizeof(*pListInfo)
1533  + nItems * sizeof(pListInfo->aItems[0]);
1534 
1535  propTemp.pVal = WBReAlloc(pListInfo, i1);
1536 
1537  if(!propTemp.pVal)
1538  {
1539  if(!pListInfo0) // extremely unlikely, if not impossible, extremely defensive code
1540  {
1541  WB_ERROR_PRINT("%s:%d %s - this should never happen\n", __FILE__, __LINE__, __FUNCTION__);
1542  DLGCListInfoDestructor(pListInfo); // destroy the one I just created
1543  }
1544 
1545  return -4;
1546  }
1547 
1548  pListInfo->nMaxItems = nItems;
1549  // now I must go to the property list entry itself and forcibly assign this new pointer
1550 
1551  if(pProp)
1552  {
1553  pProp->pVal = propTemp.pVal; // this prevents memory leaks in case of an error
1554  }
1555 
1556  pListInfo = (LISTINFO *)propTemp.pVal; // re-assign to new value
1557  }
1558 
1559  if(!cbData)
1560  {
1561 // WB_ERROR_PRINT("TEMPORARY: %s:%s:%d NULL cbData\n", __FILE__, __FUNCTION__, __LINE__);
1562  pTemp = (void *)pData;
1563  }
1564  else if(pListInfo->pfnAllocator)
1565  {
1566  pTemp = pListInfo->pfnAllocator(pData, cbData);
1567 
1569 // if(pTemp == pData)
1570 // {
1571 // WB_ERROR_PRINT("%s:%s:%d pData == pTemp %p\n", __FILE__, __FUNCTION__, __LINE__, pTemp);
1572 // }
1573  }
1574  else
1575  {
1576  pTemp = NULL;
1577  }
1578 
1579  if(pListInfo->nFlags & ListInfoFlags_SORTED) // regardless of index, when sorted, do this
1580  {
1581  // add to the end to simplify the process, then qsort
1582  pListInfo->aItems[pListInfo->nItems] = (void *)pTemp;
1583 
1584  pListInfo->nItems++;
1585 
1586  // note: QSORT_R macro needed because qsort_r differs between linux and BSD
1587  QSORT_R(pListInfo->aItems, pListInfo->nItems, sizeof(void *), pListInfo, _actual_sort_proc);
1588  }
1589  else
1590  {
1591  if(iIndex < pListInfo->nItems)
1592  {
1593  for(i1=pListInfo->nItems; i1 >= iIndex; i1--)
1594  {
1595  pListInfo->aItems[i1 + 1] = pListInfo->aItems[i1];
1596  }
1597  }
1598 
1599  pListInfo->aItems[iIndex] = (void *)pTemp;
1600 
1601  pListInfo->nItems++;
1602  }
1603 
1604  i1 = WBDialogControlSetDialogProp(pCtrl, &propTemp);
1605 
1606  if(i1)
1607  {
1608  if(!pListInfo0) // attempted to add new item and failed?
1609  {
1610  DLGCListInfoDestructor(propTemp.pVal);
1611  }
1612 
1613  return i1;
1614  }
1615 
1616 // WB_ERROR_PRINT("TEMPORARY: %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
1617 // DEBUG_DUMP_LIST(pCtrl);
1618 
1619  return 0; // meaning 'success'
1620 }
1621 
1622 void DLGDelControlListEntry(WBDialogControl *pCtrl, int iIndex)
1623 {
1624  LISTINFO *pListInfo;
1626  int i1;
1627 
1628  if(!pProp || !pProp->pVal)
1629  {
1630  WB_WARN_PRINT("%s - unable to get LISTINFO for window %d (%08xH), pProp=%p\n", __FUNCTION__,
1631  (int)pCtrl->wID, (int)pCtrl->wID, pProp);
1632  return;
1633  }
1634 
1635  pListInfo = (LISTINFO *)pProp->pVal;
1636 
1637  if(iIndex == ControlListIndex_LAST)
1638  {
1639  iIndex = pListInfo->nItems - 1;
1640  }
1641  else if(iIndex == ControlListIndex_DELETE_ALL)
1642  {
1643  if(pListInfo->pfnDestructor)
1644  {
1645  for(i1=0; i1 < pListInfo->nItems; i1++)
1646  {
1647  pListInfo->pfnDestructor(pListInfo->aItems[i1]);
1648  }
1649  }
1650 
1651  pListInfo->aItems[0] = NULL; // do this by convention
1652  pListInfo->nItems = 0;
1653 
1654  return;
1655  }
1656  else if(iIndex < 0 || iIndex >= pListInfo->nItems)
1657  {
1658  WB_ERROR_PRINT("%s - invalid index %d\n", __FUNCTION__, iIndex);
1659  return;
1660  }
1661 
1662  if(pListInfo->pfnDestructor)
1663  {
1664  pListInfo->pfnDestructor(pListInfo->aItems[iIndex]);
1665  }
1666 
1667  pListInfo->nItems--;
1668 
1669  for(i1=iIndex; i1 < pListInfo->nItems; i1++)
1670  {
1671  pListInfo->aItems[i1] = pListInfo->aItems[i1 + 1];
1672  }
1673 
1674  pListInfo->aItems[pListInfo->nItems] = NULL; // by convention
1675 
1676 // WB_ERROR_PRINT("TEMPORARY: %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
1677 // DEBUG_DUMP_LIST(pCtrl);
1678 }
1679 
1680 
1681 //typedef struct _WB_LIST_CURSEL_
1682 //{
1683 // int iCurSel; // current selection
1684 // int iTopIndex; // index of item at top of window
1685 // int iHeight; // calculated height of window in "entries" (see next member)
1686 // int iEntryHeight; // cached display height of each entry (calculated by Expose handler)
1687 //} WBListCurSel; // intended to be member following WBDialogControl for "list" controls
1688 
1689 
1690 // getting "extension" structures from dialog control structure
1691 static WBListCurSel * __GetListCurSel(WBDialogControl *pCtrl)
1692 {
1693 WBListCurSel *pSel = (WBListCurSel *)(pCtrl + 1);
1694 
1695  if(!pCtrl || !(pCtrl->ulFlags & CONTROL_SupportListInfo)
1696  || (unsigned char *)(pSel + 1) > (((unsigned char *)pCtrl) + pCtrl->cbStructSize))
1697  {
1698  return NULL;
1699  }
1700 
1701  return pSel;
1702 }
1703 
1704 
1706 {
1708 WBListCurSel *pSel = __GetListCurSel(pCtrl);
1709 
1710  if(!pSel || !pProp || !pProp->pVal)
1711  {
1712  return ControlListIndex_NONE; // "no selection"
1713  }
1714 
1715  return pSel->iCurSel;
1716 }
1717 
1719 {
1721 WBListCurSel *pSel = __GetListCurSel(pCtrl);
1722 LISTINFO *pListInfo;
1723 int iOldIndex;
1724 
1725  if(!pSel || !pProp || !pProp->pVal)
1726  {
1727  WB_WARN_PRINT("%s - unable to get LISTINFO or 'selection info' for window %d (%08xH), pSel=%p, pProp=%p\n", __FUNCTION__,
1728  (int)pCtrl->wID, (int)pCtrl->wID, pSel, pProp);
1729  return;
1730  }
1731 
1732  pListInfo = (LISTINFO *)(pProp->pVal);
1733 
1734  iOldIndex = pSel->iCurSel;
1735 
1736  if(iIndex == ControlListIndex_LAST)
1737  {
1738  pSel->iCurSel = pListInfo->nItems - 1;
1739  }
1740  else if((iIndex >= 0 && iIndex < pListInfo->nItems)
1741  || iIndex == ControlListIndex_NONE)
1742  {
1743  pSel->iCurSel = iIndex;
1744  }
1745  else
1746  {
1747  WB_WARN_PRINT("%s - invalid index %d (nItems=%d)\n", __FUNCTION__, iIndex, pListInfo->nItems);
1748  return;
1749  }
1750 
1751  if(iOldIndex != pSel->iCurSel) // notify myself that something changed
1752  {
1753  DLGNotifySelf(pCtrl, aLIST_SELCHANGE, pSel->iCurSel, iOldIndex, 0, 0, 0);
1754  }
1755 }
1756 
1757 void DLGSetControlListSelectionValue(WBDialogControl *pCtrl, int iIndex, int iSelState)
1758 {
1759 }
1760 
1761 int DLGGetControlListSelectionBits(WBDialogControl *pCtrl, unsigned int *piBits, int nSize)
1762 {
1763  return 0; // for now (warning avoidance)
1764 }
1765 
1767 {
1768 int iSel = DLGGetControlListSelection(pCtrl);
1769 
1770  if(iSel >= 0)
1771  {
1772  return WBCopyString(DLGGetControlListText(pCtrl, iSel));
1773  }
1774 
1775  // TODO: multiple selections
1776 
1777  return NULL;
1778 }
1779 
1780 
1781 
1783 // the default list control display proc
1785 
1786 void DLGCDefaultListControlDisplayProc(WBDialogControl *pList, void *pData, int iSelected, GC gc, WB_GEOM *pGeom, XFontSet fontSet)
1787 {
1788 int iHPos;
1789 Window wID = pList->wID;
1790 Display *pDisplay = WBGetWindowDisplay(wID);
1791 
1792 
1793  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_DialogCtrl,
1794  "%s - Expose %d (%08xH) pData=%p\n", __FUNCTION__, (int)wID, (int)wID, pData);
1795 
1796  if(fontSet == None)
1797  {
1798  fontSet = WBGetWindowFontSet(wID);
1799 
1800  if(fontSet == None)
1801  {
1802  fontSet = WBGetDefaultFontSet(pDisplay);
1803  }
1804  }
1805 
1806  if(fontSet == None)
1807  {
1808  // TODO: get font from dialog info
1809  WB_WARN_PRINT("%s - * BUG * line %d\n", __FUNCTION__, __LINE__);
1810  return;
1811  }
1812 
1813  iHPos = WBFontSetAvgCharWidth(pDisplay, fontSet); // average character width is new horiz pos
1814 
1815  // font setup
1817 // XClearWindow(pDisplay, wID); // TODO: rather than erase background, see if I need to
1818  XSetForeground(pDisplay, gc, iSelected ? pList->clrHBG.pixel : pList->clrBG.pixel);
1819  XFillRectangle(pDisplay, wID, gc, pGeom->x, pGeom->y, pGeom->width, pGeom->height);
1821 
1822  if(iSelected)
1823  {
1824  WBDrawDashedRect(pDisplay, wID, gc, pGeom, pList->clrBD2.pixel);
1825  }
1826 
1827 
1828  // vertically centered text
1829 // iVPos = pFont->max_bounds.ascent + pFont->max_bounds.descent; // font height
1830 // iVPos = (pGeom->height - iVPos) >> 1; // half of the difference - top of text
1831 // iVPos += pFont->max_bounds.ascent;
1832 
1833  // painting the window text
1834 
1835  if(pData)
1836  {
1837  const char *szText = (const char *)pData;
1838  WB_RECT rctBounds;
1839 
1840  rctBounds.left = pGeom->x + iHPos;
1841  rctBounds.right = pGeom->x + pGeom->width - iHPos; // equal border on right side, too
1842  rctBounds.top = pGeom->y;
1843  rctBounds.bottom = pGeom->y + pGeom->height;
1844 
1845 
1846  XSetForeground(pDisplay, gc, iSelected ? pList->clrHFG.pixel : pList->clrFG.pixel);
1847  XSetBackground(pDisplay, gc, iSelected ? pList->clrHBG.pixel : pList->clrBG.pixel);
1848 
1849  if(*szText)
1850  {
1851  DTDrawSingleLineText(fontSet, szText, pDisplay, gc, wID, 0, 0, &rctBounds,
1853  }
1854 
1855  if(iSelected) // selected item
1856  {
1857  XSetForeground(pDisplay, gc, pList->clrFG.pixel);
1858  XSetBackground(pDisplay, gc, pList->clrBG.pixel);
1859  }
1860  }
1861 
1862  // by convention, restore original objects/state
1863 
1865  XSetForeground(pDisplay, gc, WBGetWindowFGColor(wID)); // restore it at the end
1867 }
1868 
1869 
1870 
1871 
1873 // S C R O L L B A R H A N D L E R
1875 
1876 int DLGScrollBarHandler(Window wID, WBDialogControl *pCtrl, XEvent *pEvent)
1877 {
1878 int iRval, iX, iY, iDirection, iPosition;
1879 WB_SCROLLINFO *pScrollInfo;
1880 
1881 
1882  if(pEvent->type != ClientMessage)
1883  {
1884  return 0;
1885  }
1886 
1887  // look for the following:
1888  // left-button click inside of scroll bar
1889  // left button click ON the knob
1890  // left button click above/below/right-of/left-of knob
1891  // left button click on top/bottom/left/right arrow
1892 
1893  if(pEvent->xclient.message_type == aWB_POINTER)
1894  {
1895  // pointer messages - cooked mousie clickie
1896  WB_ERROR_PRINT("TEMPORARY: %s mouse message %d (%08xH) %d %d %d %d %d\n",
1897  __FUNCTION__,
1898  (int)pEvent->xclient.window, (int)pEvent->xclient.window,
1899  (int)pEvent->xclient.data.l[0],
1900  (int)pEvent->xclient.data.l[1],
1901  (int)pEvent->xclient.data.l[2],
1902  (int)pEvent->xclient.data.l[3],
1903  (int)pEvent->xclient.data.l[4]);
1904 
1906 
1907  iRval = WBScrollBarEvent(wID, pEvent, pScrollInfo);
1908  if(pScrollInfo && iRval)
1909  {
1910  return iRval; // return whatever 'WBScrollBarEvent' says to return
1911  }
1912  }
1913  else if(pEvent->xclient.message_type == aWB_CHAR)
1914  {
1915  // handle cursors only - up, down, left, right, home, end, page up, page down, etc.
1916 
1917  long lKey = pEvent->xclient.data.l[0]; // return from WBKeyEventProcessKey
1918  long lAltCtrlShift = pEvent->xclient.data.l[1]; // *piAltCtrlShift from WBKeyEventProcessKey
1919 #ifndef NO_DEBUG
1920  int nChar = (int)pEvent->xclient.data.l[2]; // # of characters decoded into pBuf (below)
1921  char *pBuf = (char *)&(pEvent->xclient.data.l[3]); // decode buffer (at least 8 chars in length)
1922 #endif // !NO_DEBUG
1923 
1924 
1925  WB_ERROR_PRINT("TEMPORARY: %s char message %lx %ld %d %s\n", __FUNCTION__, lAltCtrlShift, lKey, nChar, pBuf);
1926 
1927  if(lAltCtrlShift & WB_KEYEVENT_KEYSYM) // symbol keys only for this part
1928  {
1930 
1931  if(WB_LIKELY(pScrollInfo != NULL))
1932  {
1933  int iShift = lAltCtrlShift & WB_KEYEVENT_SHIFT;
1934  int iCtrl = lAltCtrlShift & WB_KEYEVENT_CTRL;
1935  int iAlt = lAltCtrlShift & WB_KEYEVENT_ALT;
1936  int iBar = WB_SCROLL_NA;
1937  int iDirection = WB_SCROLL_NA;
1938 
1939  switch(lKey)
1940  {
1941  case XK_Up:
1942  if(iShift || iCtrl || iAlt)
1943  {
1944  return 0;
1945  }
1946 
1947  iBar = WB_SCROLL_VERTICAL;
1948  iDirection = WB_SCROLL_BACKWARD;
1949  break;
1950 
1951  case XK_Down:
1952  if(iShift || iCtrl || iAlt)
1953  {
1954  return 0;
1955  }
1956 
1957  iBar = WB_SCROLL_VERTICAL;
1958  iDirection = WB_SCROLL_FORWARD;
1959  break;
1960 
1961  case XK_Left:
1962  if(iShift || iCtrl || iAlt)
1963  {
1964  return 0;
1965  }
1966 
1967  iBar = WB_SCROLL_HORIZONTAL;
1968  iDirection = WB_SCROLL_BACKWARD;
1969  break;
1970 
1971  case XK_Right:
1972  if(iShift || iCtrl || iAlt)
1973  {
1974  return 0;
1975  }
1976 
1977  iBar = WB_SCROLL_HORIZONTAL;
1978  iDirection = WB_SCROLL_FORWARD;
1979  break;
1980 
1981  case XK_Home:
1982 
1983  if(iShift || iAlt)
1984  {
1985  return 0;
1986  }
1987 
1988  if(iCtrl)
1989  {
1990  iBar = WB_SCROLL_VERTICAL;
1991  }
1992  else
1993  {
1994  iBar = WB_SCROLL_HORIZONTAL;
1995  }
1996 
1997  iDirection = WB_SCROLL_FIRST;
1998  break;
1999 
2000  case XK_End:
2001 
2002  if(iShift || iAlt)
2003  {
2004  return 0;
2005  }
2006 
2007  if(iCtrl)
2008  {
2009  iBar = WB_SCROLL_VERTICAL;
2010  }
2011  else
2012  {
2013  iBar = WB_SCROLL_HORIZONTAL;
2014  }
2015 
2016  iDirection = WB_SCROLL_LAST;
2017  break;
2018 
2019  case XK_Page_Up:
2020 
2021  if(iShift || iAlt)
2022  {
2023  return 0;
2024  }
2025 
2026  if(!iCtrl)
2027  {
2028  iBar = WB_SCROLL_VERTICAL;
2029  }
2030  else
2031  {
2032  iBar = WB_SCROLL_HORIZONTAL;
2033  }
2034 
2035  iDirection = WB_SCROLL_PAGEBACK;
2036  break;
2037 
2038  case XK_Page_Down:
2039 
2040  if(iShift || iAlt)
2041  {
2042  return 0;
2043  }
2044 
2045  if(!iCtrl)
2046  {
2047  iBar = WB_SCROLL_VERTICAL;
2048  }
2049  else
2050  {
2051  iBar = WB_SCROLL_HORIZONTAL;
2052  }
2053 
2054  iDirection = WB_SCROLL_PAGEFWD;
2055  break;
2056 
2057  default:
2058  return 0;
2059  }
2060 
2061  // see if the bar is actually visible first
2062  if(iBar == WB_SCROLL_HORIZONTAL)
2063  {
2064  if(pScrollInfo->geomHBar.width <= 0 || pScrollInfo->geomHBar.height <= 0)
2065  {
2066  return 0; // no vertical scroll bar
2067  }
2068  }
2069  else // vertical
2070  {
2071  if(pScrollInfo->geomVBar.width <= 0 || pScrollInfo->geomVBar.height <= 0)
2072  {
2073  return 0; // no vertical scroll bar
2074  }
2075  }
2076 
2077  DLGNotifySelf(pCtrl, aSCROLL_NOTIFY, iBar, iDirection, 0, 0, 0);
2078  return 1; // keystroke eaten
2079  }
2080  }
2081  }
2082 
2083  return 0; // NOT handled
2084 }
2085 
2086 
2087 #ifndef NO_DEBUG
2088 void DEBUG_DUMP_LIST(WBDialogControl *pCtrl)
2089 {
2090  LISTINFO *pListInfo;
2091  WB_DIALOG_PROP *pProp;
2092  int i1;
2093  const char *p1;
2094 
2095 
2096  if(WB_LIKELY((WBGetDebugLevel() & DebugLevel_MASK) < (DebugLevel_Light & DebugLevel_MASK)) ||
2097  ((WBGetDebugLevel() & DebugSubSystem_MASK) && !(DebugSubSystem_DialogCtrl & WBGetDebugLevel())))
2098  {
2099  return;
2100  }
2101 
2103 
2104  if(!pProp || !pProp->pVal)
2105  {
2106  if(!(pCtrl->ulFlags & CONTROL_SupportListInfo))
2107  {
2108  WBDebugPrint("%s - control does not support 'LISTINFO'\n", __FUNCTION__);
2109  }
2110  else
2111  {
2112  WBDebugPrint("%s - 'LISTINFO' is empty\n", __FUNCTION__);
2113  }
2114 
2115  return;
2116  }
2117 
2118  pListInfo = (LISTINFO *)pProp->pVal;
2119 
2120  if(pListInfo->nFlags & ListInfoFlags_SORTED) // regardless of index, when sorted, do this
2121  {
2122  WBDebugPrint("%s - 'LISTINFO' is sorted\n", __FUNCTION__);
2123  }
2124 
2125  WBDebugPrint("%s - 'LISTINFO' %d items\n", __FUNCTION__, pListInfo->nItems);
2126 
2127  for(i1=0; i1 < pListInfo->nItems; i1++)
2128  {
2129  // for now assume string data
2130  WBDebugPrint(" %6d: %p %s\n", i1, pListInfo->aItems[i1], (char *)(pListInfo->aItems[i1]));
2131  }
2132 }
2133 #endif // NO_DEBUG
2134 
2135 
#define WB_LIKELY(x)
optimization for code branching when condition is &#39;likely&#39;. use within conditionals ...
Atom aLOSTFOCUS
CONTROL_NOTIFY ClientMessage for LOSTFOCUS event.
int nMaxProps
maximum number of available WB_DIALOG_PROP structures in aDlgProp
Atom aDLGC_SCROLLINFO
dialog control SCROLLINFO property - see WB_SCROLLINFO structure
int cbStructSize
assigned at allocation time, the total size of this structure
2nd parameter (direction) - up, left
&#39;window helper&#39; main header file for the X11workbench Toolkit API
void DLGCListInfoDestructor(LISTINFO *pListInfo)
Destroy a LISTINFO structure.
static __inline__ Display * WBGetDefaultDisplay(void)
Returns the default Display.
Atom aGOTFOCUS
CONTROL_NOTIFY ClientMessage for GOTFOCUS event.
int nProps
current number of (contiguous) properties in &#39;aDlgProp&#39;
static __inline__ unsigned int WBGetDebugLevel(void)
Returns the current debug level assigned by WBSetDebugLevel.
Definition: debug_helper.h:124
WB_DIALOG_PROP aDlgProp[1]
Pre-allocated array of (contiguous) structures for property storage.
Atom aDLGC_PROP_NOTIFY
DLGC_PROP_NOTIFY ClientMessage, notify control of property change.
Atom aDLGC_LISTINFO
dialog control LISTINFO property - see DLGInitControlListInfo() etc.
#define WB_DEBUG_PRINT(L,...)
Preferred method of implementing conditional debug output.
Definition: debug_helper.h:299
Pixmap pixmap
foreground pixmap
void DLGDelControlListEntry(WBDialogControl *pCtrl, int iIndex)
Delete a list entry from a control&#39;s list info at a specified index (or deletes ALL entries) ...
Utilities for copying and drawing text, determining text extents, and so on.
Atom aDLGC_CONTROL_SET
CONTROL_SET ClientMessage - use this to set specific supported control properties by sending it to th...
this control supports a LISTINFO property.
Atom aPATH_TREE_CONTROL
Standard Dialog Control - path tree - directory hierarchy - see PATH_TREE_CONTROL_STR.
Pixmap pixmap2
background (transparency) pixmap
int nTop
scroll position of the top item currently displayed
generic &#39;NA&#39; or &#39;UNDEFINED&#39; value
Atom aMOUSE_DBLCLICK
CONTROL_NOTIFY ClientMessage for MOUSE_DBLCLICK event.
void DTDrawSingleLineText(XFontSet fontSet, const char *szText, Display *pDisplay, GC gc, Drawable dw, int iTabWidth, int iTabOrigin, const WB_RECT *prcBounds, int iAlignment)
draw single-line text
Definition: draw_text.c:1533
XColor clrHFG
highlighted state-based foreground color
int iCurSel
current selection
int WBScrollBarEvent(Window wID, XEvent *pEvent, WB_SCROLLINFO *pScrollInfo)
Event handler for scroll bars.
Atom aLIST_NOTIFY
CONTROL_NOTIFY ClientMessage for LIST_NOTIFY event.
XColor clrBG
background color
#define WB_KEYEVENT_ALT
&#39;AltCtrlShift&#39; bit flag for ALT modifier for WBKeyEventProcessKey()
WB_GEOM geomVBar
geometry for the vertical scroll bar excluding border (empty if not visible)
Atom aDLGC_CONTROL_GET
CONTROL_GET ClientMessage - use this to get specific supported control properties by sending it to th...
void DLGSetControlListSelection(WBDialogControl *pCtrl, int iIndex)
Assign the current selection index for a single-selection list.
Atom aKEY_DOWN
CONTROL_NOTIFY ClientMessage for KEY_DOWN event.
#define DECLARE_SORT_FUNCTION(fn_name, p0, p1, p2)
Wrapper to declare a sort function for QSORT_R.
int WBWindowDispatch(Window wID, XEvent *pEvent)
Dispatches a window XEvent. May be called directly.
int DLGAddControlListEntry(WBDialogControl *pCtrl, const char *pData, long cbData, int iIndex)
Add a list entry to a control&#39;s list info.
1st parameter (bar) - The vertical scroll bar for the control or window.
Atom aDLGC_PATH
dialog control PATH property, for file and directory controls
Atom aDEFPUSHBUTTON_CONTROL
Standard Dialog Control - default Pushbutton control (has dark border, accepts <ENTER> as hotkey) - s...
Atom aLIST_SELCHANGE
LIST_SELCHANGE ClientMessage, notify self of list selection change.
Pixmap pixmap2
background (transparency) pixmap
unsigned long ulFlags
generic flag bits
Atom aWB_CHAR
keystroke/character notifications generated by API
const void * DLGGetControlListData(WBDialogControl *pCtrl, int iIndex)
Retrieve the data pointer for a single list entry (listbox, combo, and tree controls only) ...
&#39;configuration helper&#39; main header file for the X11 Work Bench Toolkit API
int nMaxItems
max size of aItems (must re-alloc to increase nMaxItems)
unsigned long lVal
&#39;long&#39; data value, assigned as needed
void * WBReAlloc(void *pBuf, int nNewSize)
High performance memory sub-allocator &#39;re-allocate&#39;.
int DLGInitControlListInfo(WBDialogControl *pCtrl, int nFlags, void *(*pfnAllocator)(const void *, int), void(*pfnDestructor)(void *), void(*pfnDisplay)(WBDialogControl *, void *, int, GC, WB_GEOM *, XFontSet), int(*pfnSort)(const void *, const void *))
Initialize the &#39;List Entry&#39; for a control, specifying various callbacks and flags.
Atom aDIALOG_INIT
DIALOG_INIT ClientMessage, sent to dialog window callback on frame create.
XColor clrBD2
3D border color 2 (light)
int nHeight
height (in items) of display area, recalculated on resize/expose
Atom aWB_POINTER
pointer click/double-click/drag notifications generated by API
WBDialogPropList * pPropList
pointer to the property list (may be NULL)
Atom aMOUSE_CLICK
CONTROL_NOTIFY ClientMessage for MOUSE_CLICK event.
Atom aLIST_CONTROL
Standard Dialog Control - list - single, multi, extended select (h, v, multicol) - see LIST_CONTROL_S...
void WBDialogControlDelDialogProp(WBDialogControl *pCtrl, Atom aProp)
Low-level dialog control property removal.
Atom aRADIOBUTTON_CONTROL
Standard Dialog Control - radio button - see RADIOBUTTON_CONTROL_STR.
const char * WBDialogControlGetProperty(WBDialogControl *pCtrl, Atom aPropName)
Mid-level dialog control property retrieval (character string)
Atom aClass
basic control class atom
Atom aSCROLL_NOTIFY
Atom aSLIDER_CONTROL
Standard Dialog Control - volume control (slider bar) (h or v depending on geometry) - see SLIDER_CON...
void WBInvalidateGeom(Window wID, const WB_GEOM *pGeom, int bPaintNow)
&#39;Paint&#39; helper, invalidates a geometry for asynchronous Expose event generation
XColor clrHBG
highlighted state-based background color
1st parameter (bar) - The horizontal scroll bar for the control or window
Structure that defines scroll bar info for both horizontal and vertical scroll bars.
void WBDialogControlSetIconPixmap(WBDialogControl *pCtrl, Pixmap pixmap, Pixmap pixmap2)
Assign the ICON (image) property for a control, which consists of 2 pixmaps.
Window wID
Window ID of the dialog control window.
void(* pfnDisplay)(WBDialogControl *pControl, void *pData, int iSelected, GC gcPaint, WB_GEOM *pGeom, XFontSet fontSet)
display callback function to paint the entry on the display surface
Window wOwner
owning window [to be notified on change]
unsigned long WBGetWindowFGColor(Window wID)
Returns the currently assigned foreground color.
center using entire text height (ascent + descent for single line)
Definition: draw_text.h:86
void(* pfnDestructor)(void *)
destructor to call for each item that&#39;s removed
Atom aTAB_CONTROL
Standard Dialog Control -&#39;tab&#39; container (auto enable/disable contents) - see TAB_CONTROL_STR.
2nd parameter (direction) - bottom, end
Atom aTEXT_CONTROL
Standard Dialog Control - static text (single or multi-line) - see TEXT_CONTROL_STR.
LISTINFO * DLGCListInfoConstructor(Window wOwner, int nMax, int nFlags, void *(*pfnAllocator)(const void *, int), void(*pfnDestructor)(void *), void(*pfnDisplay)(WBDialogControl *, void *, int, GC, WB_GEOM *, XFontSet), int(*pfnSort)(const void *, const void *))
Create LISTINFO structure for a list type control.
Atom aDLGC_FONT
dialog control FONT property - reserved
void * WBAlloc(int nSize)
High performance memory sub-allocator &#39;allocate&#39;.
unsigned int width
#define END_XCALL_DEBUG_WRAPPER
wrapper macro for calls into the X11 library. This macro follows the call(s)
Pixmap WBDialogControlGetPixmap(WBDialogControl *pCtrl)
Obtain the assigned PIXMAP (image) property for a control.
int WBDialogControlSetDialogProp(WBDialogControl *pCtrl, WB_DIALOG_PROP *pPropVal)
Low-level dialog control property assignment.
unsigned int height
Button &#39;pushbutton&#39; control structure.
Atom aCOMBO_CONTROL
Standard Dialog Control - classic &#39;combo box&#39; control - see COMBO_CONTROL_STR.
int DLGGetControlListSelectionBits(WBDialogControl *pCtrl, unsigned int *piBits, int nSize)
Query the selection state for multiple items within a control&#39;s list info.
Dialog property storage structure.
int WBFontSetAvgCharWidth(Display *pDisplay, XFontSet fontSet)
Get the average character width for a font set.
Definition: font_helper.c:1227
#define WB_ERROR_PRINT(...)
Preferred method of implementing an &#39;error level&#39; debug message for all subsystems.
Definition: debug_helper.h:356
Atom aDLGC_CAPTION
dialog control CAPTION property - see WBDialogControlGetCaption()
char * DLGGetControlListSelectionText(WBDialogControl *pCtrl)
Query the selection text as multiple strings in an allocated buffer.
Atom aFILE_COMBO_CONTROL
Standard Dialog Control - file combo control - see FILE_COMBO_CONTROL_STR.
int WBDialogControlSetPropList(WBDialogControl *pCtrl, const char *szPropList)
Mid-level dialog control property list assignment.
Atom aVSCROLL_CONTROL
Standard Dialog Control - vertical scroll - see VSCROLL_CONTROL_STR.
Atom aDLGC_TEXT
dialog control TEXT property - see WBDialogControlGetText()
#define QSORT_R(base, nmemb, size, thunk, compar)
Local implementation of qsort_r() for operating systems that do not have it.
struct __WB_DIALOG_PROPLIST__ WBDialogPropList
Dialog Property List, container for WB_DIALOG_PROP.
void WBFree(void *pBuf)
High performance memory sub-allocator &#39;free&#39;.
2nd parameter (direction) - pgup, pgleft
#define WB_KEYEVENT_SHIFT
&#39;AltCtrlShift&#39; bit flag for Shift modifier for WBKeyEventProcessKey()
Atom aCOMBOTREE_CONTROL
Standard Dialog Control - &#39;combo tree&#39; (tree with interlocked edit/text box like combo box) - see COM...
int nItems
current number of valid entries in &#39;aItems&#39;
int nPos
current scroll position
void WBUpdateWindow(Window wID)
&#39;Paint&#39; helper, generates an asynchronous Expose event for non-empty &#39;invalid&#39; region ...
Atom aEDIT_CONTROL
Standard Dialog Control - editable text (single or multi-line, scrollable, clipboard) - see EDIT_CONT...
Atom aProp
Atom identifying the property.
int WBDialogControlGetCheck(WBDialogControl *pCtrl)
Retrieve the &#39;CHECKED&#39; property from a dialog control. Returns &#39;0&#39; (un-checked) if not applicable...
Dialog Property List, container for WB_DIALOG_PROP.
int nFlags
flags (sorted, etc.)
A &#39;C++&#39;-like object for managing text, can be overridden.
Atom aKEYSTROKE
CONTROL_NOTIFY ClientMessage for KEYSTROKE event.
internal wrapper struct for &#39;rectangle&#39; definition
void DLGCDefaultListControlDisplayProc(WBDialogControl *pList, void *pData, int iSelected, GC gc, WB_GEOM *pGeom, XFontSet fontSet)
The default &#39;display proc&#39; for displaying a list item from a LISTINFO structure.
WB_GEOM geomHBar
geometry for the horizontal scroll bar excluding border (empty if not visible)
void DLGCDestroyProperties(WBDialogPropList *pPropList)
Destroy Properties for a dialog control.
void * WBDialogControlGetProperty2(WBDialogControl *pCtrl, Atom aPropName)
Mid-level dialog control property list retrieval (generic pointer)
Atom aCANCELBUTTON_CONTROL
Standard Dialog Control - cancel pushbutton control (accepts <ESC> as hotkey) - see CANCELBUTTON_CONT...
Structure identifying the properties of a dialog box control.
Atom aHSCROLL_CONTROL
Standard Dialog Control - horizontal scroll - see HSCROLL_CONTROL_STR.
2nd parameter (direction) - home, top
Atom aCHECKBUTTON_CONTROL
Standard Dialog Control - check[box] button - push-on/push-off with &#39;check mark&#39; (or whatever) - see ...
Atom aKEY_UP
CONTROL_NOTIFY ClientMessage for KEY_UP event.
XColor clrFG
foreground color
Atom aMOUSE_DRAG
CONTROL_NOTIFY ClientMessage for MOUSE_DRAG event.
const char * WBDialogControlGetCaption(WBDialogControl *pCtrl)
Obtain a pointer to the assigned text for the &#39;CAPTION&#39; property of a dialog control.
const WB_DIALOG_PROP * WBDialogControlGetDialogProp(WBDialogControl *pCtrl, Atom aProp)
Low-level dialog control property retrieval.
Static &#39;Image&#39; control structure.
Atom aIMAGE_CONTROL
Standard Dialog Control - generic image/pixmap holder - see IMAGE_CONTROL_STR.
Atom aTEXTSELECT_CHANGE
CONTROL_NOTIFY ClientMessage for TEXTSELECT_CHANGE event.
char * pCaption
allocated pointer to caption, in lieu of using a WM_NAME property (may be NULL)
Display * WBGetWindowDisplay(Window wID)
returns the Display associated with a window
int DLGGetControlListSelection(WBDialogControl *pCtrl)
Obtain the current selection index for a single-selection list.
void DLGSetControlListSelectionValue(WBDialogControl *pCtrl, int iIndex, int iSelState)
Assign the selection state for a specific index within a control&#39;s list info.
Atom aKNOB_CONTROL
Standard Dialog Control - "volume knob" (270 degrees of rotation, left to right) - see KNOB_CONTROL_S...
2nd parameter (direction) - pgdn, pgright
Atom aFIRSTRADIOBUTTON_CONTROL
Standard Dialog Control - &#39;first&#39; radio button - defines start of radio button &#39;group&#39; - see FIRSTRAD...
Atom aTREE_CONTROL
Standard Dialog Control - class &#39;tree&#39; control - see TREE_CONTROL_STR.
int(* pfnSort)(const void *, const void *)
Optional sort comparison function. NULL implies &#39;strcmp&#39;.
Structure containing data for list-related dialog controls.
#define BEGIN_XCALL_DEBUG_WRAPPER
wrapper macro for calls into the X11 library. This macro precedes the call(s)
int DLGModifyControlListInfo(WBDialogControl *pCtrl, int bFlags, int nFlags, int bAllocator, void *(*pfnAllocator)(const void *, int), int bDestructor, void(*pfnDestructor)(void *), int bDisplay, void(*pfnDisplay)(WBDialogControl *, void *, int, GC, WB_GEOM *, XFontSet), int bSort, int(*pfnSort)(const void *, const void *))
Modify the &#39;List Entry&#39; for a control, specifying various callbacks and flags.
Structure containing information about the current selection in a list.
int DLGScrollBarHandler(Window wID, WBDialogControl *pCtrl, XEvent *pEvent)
Scroll bar event filter for dialog control callback function. Generates scroll events.
Atom aBUTTON_PRESS
CONTROL_NOTIFY ClientMessage for BUTTON_PRESS event.
void WBDebugPrint(const char *pFmt,...) __attribute__((format(printf
conditional debug message output
#define WB_KEYEVENT_CTRL
&#39;AltCtrlShift&#39; bit flag for Control modifier for WBKeyEventProcessKey()
Atom aICON_CONTROL
Standard Dialog Control - icon container (has a nice 3D border) - see ICON_CONTROL_STR.
left-justified text
Definition: draw_text.h:77
Atom aTRISTATEBUTTON_CONTROL
Standard Dialog Control - tristate - like check, but with a third state - see TRISTATEBUTTON_CONTROL_...
static __inline__ void DLGNotifySelf(WBDialogControl *pDialogControl, Atom aNotify, long lData0, long lData1, long lData2, long lData3, long lData4)
Notify &#39;self&#39; by calling the window&#39;s own callback function directly with an event.
char * WBCopyString(const char *pSrc)
A simple utility that returns a WBAlloc() copy of a 0-byte terminated string.
Atom aFRAME_CONTROL
Standard Dialog Control - transparent frame with optional text - see FRAME_CONTROL_STR.
void *(* pfnAllocator)(const void *, int)
pointer to the copy constructor to call for each item that&#39;s added
XFontSet WBGetWindowFontSet(Window wID)
Returns the current XFontSet assigned to the window (may be None)
int WBDialogControlSetProperty(WBDialogControl *pCtrl, Atom aPropName, const char *szPropVal)
Mid-level dialog control property assignment (character string)
Atom aFILE_LIST_CONTROL
Standard Dialog Control - File List - see FILE_LIST_CONTROL_STR.
Pixmap WBDialogControlGetIconPixmap(WBDialogControl *pCtrl, Pixmap *pPixmap2)
Obtain the assigned ICON (image) property for a control, which consists of 2 pixmaps.
2nd parameter (direction) - down, right
void * DLGCDefaultListInfoAllocator(const void *pData, int cbData)
The default &#39;List Info&#39; data allocator for a control&#39;s list info.
void WBDialogControlSetCheck(WBDialogControl *pCtrl, int iCheck)
Assign the TEXT property for a control, which is different from the CAPTION or Title.
Atom aPUSHBUTTON_CONTROL
Standard Dialog Control - Pushbutton control - see PUSHBUTTON_CONTROL_STR.
void WBDialogControlsInit(void)
Initialization function for dialog controls.
void WBDialogControlSetPixmap(WBDialogControl *pCtrl, Pixmap pixmap)
Assign the PIXMAP (image) property for a control.
internal wrapper struct for X11 &#39;geometry&#39; definition
always insert at beginning
const char * DLGGetControlListText(WBDialogControl *pCtrl, int iIndex)
Retrieve the text poiner for a single list entry (listbox, combo, and tree controls only) ...
void WBDialogControlSetCaption(WBDialogControl *pCtrl, const char *szCaption)
Assign text to the &#39;CAPTION&#39; property of a dialog control.
#define WB_WARN_PRINT(...)
Preferred method of implementing a &#39;warning level&#39; debug message for all subsystems.
Definition: debug_helper.h:349
void * pVal
pointer to data, as needed (may be allocated, some property types auto-free the data) ...
void * aItems[1]
The array of item data, integrated into the memory block containing this structure.
XFontSet WBGetDefaultFontSet(Display *pDisplay)
Returns an XFontSet for the default font.
void WBDialogControlSetProperty2(WBDialogControl *pCtrl, Atom aPropName, void *pPropVal)
Mid-level dialog control property list assignment (generic pointer)
Atom aTEXT_CHANGED
CONTROL_NOTIFY ClientMessage for TEXT_CHANGED event.
&#39;checked&#39; flag. when &#39;setting&#39;, -1 &#39;toggles&#39;, 1 sets it, 0 clears it. when &#39;getting&#39;, zero is &#39;unchecked&#39;, non-zero &#39;checked&#39;
Pixmap pixmap
foreground pixmap
void WBDrawDashedRect(Display *pDisplay, Drawable wID, GC gc, WB_GEOM *pgeomRect, unsigned long lColor)
Draw a &#39;dashed&#39; rectangle.
#define WB_KEYEVENT_KEYSYM
&#39;AltCtrlShift&#39; bit flag for &#39;VK_&#39; keys for WBKeyEventProcessKey()