home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / c / e_gem140 / source / dial.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-15  |  77.0 KB  |  3,597 lines

  1.  
  2. #include <time.h>
  3. #include <stdio.h>
  4. #include <ctype.h>
  5.  
  6. #ifndef __MINT_LIB__
  7. #include <stdlib.h>
  8. #endif
  9.  
  10. #include <string.h>
  11. #include "proto.h"
  12.  
  13. #define DEFAULT_ERR        "[1][ Zu viele DEFAULT-Schalter! | Nur ein DEFAULT-Schalter | pro Baum möglich! ][ Ok ]"
  14. #define INDDEFAULT_ERR    "[1][ Zu viele INDDEFAULT-Objekte! | Nur ein INDDEFAULT-Objekt | pro Baum möglich! ][ Ok ]"
  15. #define HELP_ERR        "[1][ Zu viele HELP-Objekte! | Nur ein HELP-Objekt | pro Baum möglich! ][ Ok ]"
  16. #define UNDO_ERR        "[1][ Zu viele UNDO-Objekte! | Nur ein UNDO-Objekt | pro Baum möglich! ][ Ok ]"
  17.  
  18. #define CHKHOTKEY_ERR_A    "[1][ CHKHOTKEY-Fehler: | Das Text-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  19. #define CHKHOTKEY_ERR_B "[1][ CHKHOTKEY-Fehler: | Das HOTKEY-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  20. #define RBHOTKEY_ERR_A    "[1][ RBHOTKEY-Fehler: |  Das Text-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  21. #define RBHOTKEY_ERR_B    "[1][ RBHOTKEY-Fehler: | Das HOTKEY-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  22.  
  23. #define HOTKEY_ERR        "[1][ HOTKEY-Fehler: | doppelter HOTKEY '%c'! | (Objekt-Nummer %d) ][ Ok ]"
  24.  
  25. #define SCANRET     28
  26. #define SCANENTER    114
  27. #define SCANUNDO    97
  28. #define SCANHELP    98
  29. #define SCANUP        72
  30. #define SCANDOWN    80
  31. #define SCANLEFT    75
  32. #define CTRLLEFT    115
  33. #define CTRLRIGHT    116
  34. #define SCANRIGHT    77
  35. #define SCANTAB     15
  36. #define SCANHOME    71
  37. #define SCANDEL     83
  38. #define SCANINS     82
  39.  
  40. #define WIN_ELEMENTE NAME|MOVER
  41.  
  42. typedef struct
  43. {
  44.     char            *string;
  45.     USERBLK         text_blk;
  46.     int             font,color,center;
  47. } V_TEXT;
  48.  
  49. typedef struct _list
  50. {
  51.     V_TEXT            *start;
  52.     int             index;
  53.     struct _list    *next;
  54. } V_LIST;
  55.  
  56. typedef struct
  57. {
  58.     long    type;
  59.     long    what;
  60. } APPLRECORD;
  61.  
  62. const char __ident_e_gem[] = "Id: $EnhancedGEM v" E_GEM_VERSION " $";
  63.  
  64. boolean _back_win;
  65. DIAINFO *_dia_list[128],*dinfo;
  66. int _dia_len,_bevent;
  67.  
  68. static char umlaute[] = "_äöüÄÖÜß";
  69. static char string_0[] = " ASCII-Table ";
  70. static char string_1[] = " \x01" "\x02" "\x03" "\x04" "\x05" "\x06" "\x07" "\x08" "\x09" "\x0a" "\x0b" "\x0c" "\x0d" "\x0e" "\x0f" "\x10" "\x11" "\x12" "\x13" "\x14" "\x15" "\x16" "\x17" "\x18" "\x19" "\x1a" "\x1b" "\x1c" "\x1d" "\x1e" "\x1f" "";
  71. static char string_2[] = " !\"#$%&\'()*+,-./0123456789:;<=>?";
  72. static char string_3[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
  73. static char string_4[] = "`abcdefghijklmnopqrstuvwxyz{|}~\x7f" "";
  74. static char string_5[] = "\x80" "ü\x82" "\x83" "ä\x85" "\x86" "\x87" "\x88" "\x89" "\x8a" "\x8b" "\x8c" "\x8d" "Ä\x8f" "\x90" "\x91" "\x92" "\x93" "ö\x95" "\x96" "\x97" "\x98" "ÖÜ\x9b" "\x9c" "\x9d" "ß\x9f" "";
  75. static char string_6[] = "\xa0" "\xa1" "\xa2" "\xa3" "\xa4" "\xa5" "\xa6" "\xa7" "\xa8" "\xa9" "\xaa" "\xab" "\xac" "\xad" "\xae" "\xaf" "\xb0" "\xb1" "\xb2" "\xb3" "\xb4" "\xb5" "\xb6" "\xb7" "\xb8" "\xb9" "\xba" "\xbb" "\xbc" "\xbd" "\xbe" "\xbf" "";
  76. static char string_7[] = "\xc0" "\xc1" "\xc2" "\xc3" "\xc4" "\xc5" "\xc6" "\xc7" "\xc8" "\xc9" "\xca" "\xcb" "\xcc" "\xcd" "\xce" "\xcf" "\xd0" "\xd1" "\xd2" "\xd3" "\xd4" "\xd5" "\xd6" "\xd7" "\xd8" "\xd9" "\xda" "\xdb" "\xdc" "\xdd" "\xde" "\xdf" "";
  77. static char string_8[] = "\xe0" "\xe1" "\xe2" "\xe3" "\xe4" "\xe5" "\xe6" "\xe7" "\xe8" "\xe9" "\xea" "\xeb" "\xec" "\xed" "\xee" "\xef" "\xf0" "\xf1" "\xf2" "\xf3" "\xf4" "\xf5" "\xf6" "\xf7" "\xf8" "\xf9" "\xfa" "\xfb" "\xfc" "\xfd" "\xfe" "\xff" "";
  78. static char string_9[] = "Cancel";
  79.  
  80. static OBJECT ascii_tree[] = {
  81.     { -1, 1, 13, G_BOX, NONE, OUTLINED,CAST (0x21141L), 0,512, 36,14 },
  82.     { 11, 2, 10, G_BOX, NONE, NORMAL,CAST (0xFF1101L), 2,3073, 32,777 },
  83.     { 3, -1, -1, (HEADER<<8)+G_BUTTON, NONE, NORMAL,CAST string_0, 1,0, 13,1 },
  84.     { 4, -1, -1, G_STRING, TOUCHEXIT, NORMAL,CAST string_1, 0,1, 32,1 },
  85.     { 5, -1, -1, G_STRING, TOUCHEXIT, NORMAL,CAST string_2, 0,3, 32,1 },
  86.     { 6, -1, -1, G_STRING, TOUCHEXIT, NORMAL,CAST string_3, 0,2, 32,1 },
  87.     { 7, -1, -1, G_STRING, TOUCHEXIT, NORMAL,CAST string_4, 0,4, 32,1 },
  88.     { 8, -1, -1, G_STRING, TOUCHEXIT, NORMAL,CAST string_5, 0,5, 32,1 },
  89.     { 9, -1, -1, G_STRING, TOUCHEXIT, NORMAL,CAST string_6, 0,6, 32,1 },
  90.     { 10,-1, -1, G_STRING, TOUCHEXIT, NORMAL,CAST string_7, 0,7, 32,1 },
  91.     { 1, -1, -1, G_STRING, TOUCHEXIT, NORMAL,CAST string_8, 0,8, 32,1 },
  92.     { 13, 12, 12, G_BUTTON, SELECTABLE|DEFAULT|EXIT, NORMAL,CAST string_9, 22,3851, 12,1025 },
  93.     { 11, -1, -1, (HOTKEY<<8)+G_IBOX, NONE, NORMAL,CAST (0x43011100L), 3,512, 1,1 },
  94.     { 0, -1, -1, (FLYDIAL<<8)+G_IBOX, SELECTABLE|LASTOB, NORMAL,CAST (0x57011100L), 34,0, 2,1 },
  95. };
  96.  
  97. #define ASC0    3
  98. #define CANCEL    11
  99.  
  100. static char *c_arrow[] = {"\x04","\x03","\x01","\x02"};
  101.  
  102. static APPLRECORD record[] = {
  103. {1l,0x10000l}, {0l,10l}, {1l,0x100001l}};
  104.  
  105. static int        *cycle_but,*box_on,*box_off,*radio_on,*radio_off;
  106. static int        *arrow_up,*arrow_up_sel,*arrow_down,*arrow_down_sel;
  107. static int        *arrow_left,*arrow_left_sel,*arrow_right,*arrow_right_sel;
  108. static int        x_events,win_top,modal,mouse_flag,key_taken,ac_close,_asc,exit_obj,gr_dcw;
  109. static boolean    init_flag,w_init,x_abort,dial,call_func,always_keys;
  110. static char     undobuff[128];
  111. static EVENT    *_event;
  112.  
  113. static V_TEXT    v_text[128];
  114. static V_LIST    v_list = {v_text,0,NULL};
  115.  
  116. static char     history[20][80];
  117. static int        hist_index;
  118.  
  119. static int         (*xf_init)(EVENT *);
  120. static void        (*xf_msg)(EVENT *);
  121.  
  122. static DIAINFO *win_list[128];
  123. static int        win_len = 0,dial_pattern = 0,dial_color = BLACK;
  124. static int        image_w,image_h,big_img;
  125. static boolean    nonsel_fly = FALSE,dial_tframe = TRUE,dial_tsmall = FALSE,dial_round = TRUE,dial_title = FALSE;
  126. static boolean  return_default = TRUE,menu_nice = TRUE;
  127.  
  128. static int cdecl draw_fly(PARMBLK *);
  129. static int cdecl draw_text(PARMBLK *);
  130. static int cdecl draw_underline(PARMBLK *);
  131. static int cdecl draw_cyclebutton(PARMBLK *);
  132. static int cdecl draw_box(PARMBLK *);
  133. static int cdecl draw_radiobutton(PARMBLK *);
  134. static int cdecl draw_arrows(PARMBLK *);
  135. static int cdecl draw_menu(PARMBLK *);
  136.  
  137. static USERBLK    cycleblk = {draw_cyclebutton,1};
  138. static USERBLK    flyblk = {draw_fly,0};
  139. static USERBLK    hotkeyblk = {draw_underline,1};
  140. static USERBLK    checkblk = {draw_box,1};
  141. static USERBLK    rbuttblk = {draw_radiobutton,1};
  142. static USERBLK    unlnblk = {draw_underline,0x0101l};
  143. static USERBLK    arrows = {draw_arrows,1};
  144. static USERBLK  menublk = {draw_menu,0};
  145.  
  146. static void     open_flydialog(OBJECT *,DIAINFO *,boolean,boolean);
  147. static boolean    open_windialog(OBJECT *,DIAINFO *,char *,int,boolean,boolean);
  148. static void        close_dials(void);
  149.  
  150. static boolean    win_topped(DIAINFO *);
  151. static void     init_xformdo(int,EVENT *,boolean);
  152. static void     dial_center(OBJECT *,boolean,int,int);
  153. static void     dial_pos(OBJECT *,int,int);
  154. static void     find_fly(DIAINFO *);
  155. static void     test_inddefault(OBJECT *,OBJECT *);
  156.  
  157. static void     vdi_trans(int,int,void *);
  158. static void     scale_img(int *,int,int,int,int *,int *);
  159. static void     scale_coords(int *,int *);
  160.  
  161. static void     cursor(int);
  162. static void     edit_off(void);
  163. static void     edit_on(void);
  164. static void     sel_edit(OBJECT *,int,boolean);
  165. static void     first_edit(OBJECT *);
  166. static void     last_edit(OBJECT *);
  167. static void     next_edit(OBJECT *);
  168. static void     prev_edit(OBJECT *);
  169. static void     edit_pos(int,boolean);
  170. static void     edit_string(char *);
  171. static void     edit_objc(OBJECT *,int,int,int *,int);
  172. static void     edit_rect(OBJECT *,int,VRECT *,int *);
  173.  
  174. static void     mouse_cursor(EVENT *);
  175. static int        klickobj(DIAINFO *,EVENT *,int *,boolean);
  176. static int        key_handler(OBJECT *,int,int,EVENT *);
  177. static int        cursor_handler(OBJECT *,int,int,EVENT *);
  178. static int        objekt_handler(DIAINFO *,int,int,int,int,boolean,boolean);
  179.  
  180. static int        is_rb_chk(OBJECT *,int);
  181. static boolean    is_editable(OBJECT *,int,int);
  182. static boolean    is_hidden(OBJECT *,int,boolean);
  183.  
  184. static void     do_jump_fly(OBJECT *,int,int);
  185. static boolean    word_ascii(char);
  186. static void     insert_history(char *);
  187.  
  188. static void     clipbrd_load(boolean);
  189. static boolean    clipbrd_save(int);
  190.  
  191. static boolean    find_window(int,DIAINFO **);
  192. static void     top_window(EVENT *,DIAINFO *);
  193.  
  194. static void     get_image(IMAGES *,int,BUTTON *,int **,int **);
  195. static void     set_images(IMAGES *,int **,int **);
  196.  
  197. static int        do_func(int,EVENT *);
  198. static void        re_init(EVENT *);
  199. static void     vrt_copy(int *,PARMBLK *,int,int);
  200.  
  201. void dial_options(boolean round,boolean t_frame,boolean t_small,boolean niceline,boolean ret,boolean back,boolean nonsel,boolean keys)
  202. {
  203.     always_keys = keys;
  204.     dial_round    = round;
  205.     dial_tframe = t_frame;
  206.     dial_tsmall = t_small;
  207.     menu_nice    = niceline;
  208.     return_default    = ret;
  209.     nonsel_fly    = nonsel;
  210.  
  211.     if (aes_version>0x0100)
  212.         _back_win = back;
  213.     else
  214.         _back_win = FALSE;
  215.  
  216.     if (_back_win && _bevent)
  217.     {
  218.         reg int i;
  219.         for (i=0;i<win_len;i++)
  220.             wind_set(win_list[i]->di_handle,WF_BEVENT,back);
  221.     }
  222. }
  223.  
  224. void dial_colors(int d_pattern,int d_color,int popup,int hotkey,int check,int radio,int arrow)
  225. {
  226.     dial_color     = d_color;
  227.     dial_pattern = d_pattern;
  228.  
  229.     cycleblk.ub_parm    = popup;
  230.     hotkeyblk.ub_parm    = hotkey;
  231.     checkblk.ub_parm    = check;
  232.     rbuttblk.ub_parm    = radio;
  233.     arrows.ub_parm        = arrow;
  234. }
  235.  
  236. void title_options(boolean title,int color,int size)
  237. {
  238.     dial_title    = title;
  239.     unlnblk.ub_parm = (size<<8)|color;
  240. }
  241.  
  242. void get_image(IMAGES *img,int index,BUTTON *but,int **img_on,int **img_off)
  243. {
  244.     reg int *on = NULL,*off;
  245.  
  246.     if (index>=0 && index<img->count)
  247.     {
  248.         on    = img->image[index].hi_on;
  249.         off = img->image[index].hi_off;
  250.     }
  251.     else if (but)
  252.     {
  253.         on = but->but_on;
  254.         off = but->but_off;
  255.     }
  256.     
  257.     if (on)
  258.     {
  259.         *img_on = on;
  260.         if (img_off)
  261.             *img_off= off;
  262.     }
  263. }
  264.  
  265. void radio_image(int index,BUTTON *radio)
  266. {
  267.     get_image(&radios,index,radio,&radio_on,&radio_off);
  268. }
  269.  
  270. void check_image(int index,BUTTON *check)
  271. {
  272.     get_image(&checks,index,check,&box_on,&box_off);
  273. }
  274.  
  275. void arrow_image(int index,BUTTON *down,BUTTON *up,BUTTON *left,BUTTON *right)
  276. {
  277.     get_image(&arrows_left,index,left,&arrow_left_sel,&arrow_left);
  278.     get_image(&arrows_right,index,right,&arrow_right_sel,&arrow_right);
  279.     get_image(&arrows_down,index,down,&arrow_down_sel,&arrow_down);
  280.     get_image(&arrows_up,index,up,&arrow_up_sel,&arrow_up);
  281. }
  282.  
  283. void cycle_image(int index,BUTTON *cycle)
  284. {
  285.     get_image(&cycles,index,cycle,&cycle_but,NULL);
  286. }
  287.  
  288. boolean init_gem(char *m_entry)
  289. {
  290.     if (init_flag)
  291.         return(TRUE);
  292.  
  293.     AES_VERSION = 0;
  294.     if ((ap_id = appl_init())>=0 && (aes_version = AES_VERSION)>0)
  295.     {
  296.         int dummy,work_out[57];
  297.  
  298.         grhandle = graf_handle(&gr_cw,&gr_ch,&gr_bw,&gr_bh);
  299.         gr_dcw = gr_cw<<1;
  300.  
  301.         if (open_work(&x_handle,work_out))
  302.         {
  303.             long value;
  304.             if (get_cookie(COOKIE_MAGX,&value))
  305.             {
  306.                 magx = ((int **) value)[2][24];
  307.                 if (magx<0x0200)
  308.                     magx = 0;
  309.             }
  310.  
  311.             if (m_entry && (!_app || aes_version>=0x0400))
  312.                 menu_id = menu_register(ap_id,m_entry);
  313.             else
  314.                 menu_id = -1;
  315.  
  316.             max_w = work_out[0];
  317.             max_h = work_out[1];
  318.             colors = work_out[39];
  319.  
  320.             vq_extnd(x_handle,1,work_out);
  321.             planes = work_out[4];
  322.  
  323.             appl_getfontinfo(0,&ibm_font,&ibm_font_id,&dummy);
  324.             appl_getfontinfo(1,&small_font,&small_font_id,&dummy);
  325.  
  326.             vst_font(x_handle,small_font_id);
  327.             vst_height(x_handle,small_font,&dummy,&dummy,&gr_sw,&gr_sh);
  328.  
  329.             vs_attr();
  330.             v_set_text(ibm_font_id,ibm_font,BLACK,NULL);
  331.             vst_alignment(x_handle,0,5,&dummy,&dummy);
  332.  
  333.             v_set_mode(MD_REPLACE);
  334.             v_set_line(BLACK,1);
  335.             vsl_type(x_handle,1);
  336.             vsl_ends(x_handle,0,0);
  337.             vsl_udsty(x_handle,0x5555);
  338.  
  339.             v_set_fill(BLACK,1,1);
  340.             vsf_perimeter(x_handle,1);
  341.  
  342.             if (gr_cw<8 || gr_ch<8)
  343.             {
  344.                 image_w = min(gr_dcw,16);
  345.                 image_h = min(gr_ch,16);
  346.                 big_img = FAIL;
  347.             }
  348.             else if (gr_ch>15)
  349.             {
  350.                 image_w = image_h = 16;
  351.                 big_img = TRUE;
  352.             }
  353.             else
  354.             {
  355.                 image_w = 16;
  356.                 image_h = 8;
  357.                 big_img = FALSE;
  358.             }
  359.  
  360.             set_images(&radios,&radio_on,&radio_off);
  361.             set_images(&checks,&box_on,&box_off);
  362.             set_images(&arrows_left,&arrow_left_sel,&arrow_left);
  363.             set_images(&arrows_right,&arrow_right_sel,&arrow_right);
  364.             set_images(&arrows_up,&arrow_up_sel,&arrow_up);
  365.             set_images(&arrows_down,&arrow_down_sel,&arrow_down);
  366.             set_images(&cycles,&cycle_but,NULL);
  367.  
  368.             if (wind_get(0,WF_RETURN,&dummy,&dummy,&dummy,&dummy)==0)
  369.             {
  370.                 int version;
  371.                 wind_get(0,WF_WINX,&version,&dummy,&dummy,&dummy);
  372.                 winx = (version & 0x0fff);
  373.                 if (winx<0x0210)
  374.                     winx = 0;
  375.             }
  376.  
  377.             _bevent = (aes_version>0x0331 || winx || magx);
  378.             wind_get(0,WF_WORKXYWH,&desk.g_x,&desk.g_y,&desk.g_w,&desk.g_h);
  379.             rc_grect_to_array(&desk,(int *) &clip);
  380.             _set_clip((int *) &clip);
  381.  
  382.             rsrc_calc(ascii_tree,SCALING);
  383.             scrp_init(NULL);
  384.             graf_mouse(ARROW,NULL);
  385.             if (aes_version>=0x0400)
  386.                 shel_write(9,0,0x01,"","");
  387.  
  388.             init_flag = TRUE;
  389.             return(TRUE);
  390.         }
  391.         else
  392.         {
  393.             appl_exit();
  394.             return(FAIL);
  395.         }
  396.     }
  397.     else
  398.         return(FALSE);
  399. }
  400.  
  401. int appl_getinfo(int ap_gtype,int *ap_gout1,int *ap_gout2,int *ap_gout3,int *ap_gout4)
  402. {
  403.     reg int *array;
  404.  
  405.     INTIN[0] = ap_gtype;
  406.     _aes(0,0x82010500L);
  407.  
  408.     array = &INTOUT[5];
  409.     *ap_gout4 = *--array;
  410.     *ap_gout3 = *--array;
  411.     *ap_gout2 = *--array;
  412.     *ap_gout1 = *--array;
  413.     return(*--array);
  414. }
  415.  
  416. static int has_agi = FAIL;
  417.  
  418. int appl_xgetinfo(int type,int *out1,int *out2,int *out3,int *out4)
  419. {
  420.     if (has_agi<0)
  421.         has_agi = (aes_version>=0x400 || magx || winx || appl_find("?AGI")==0) ? TRUE : FALSE;
  422.  
  423.     if (has_agi)
  424.         return (appl_getinfo(type,out1,out2,out3,out4));
  425.     else
  426.         return(0);
  427. }
  428.  
  429. int appl_getfontinfo(int ap_gtype,int *height,int *id,int *type)
  430. {
  431.     int dummy,attrib[10];
  432.  
  433.     vs_attr();
  434.  
  435.     if (appl_xgetinfo(ap_gtype,height,id,type,&dummy))
  436.     {
  437.         if (*id==-12124)
  438.             *id = 1;
  439.  
  440.         if (vst_font(x_handle,*id)!=*id && fonts_loaded<0 && vq_gdos())
  441.             fonts_loaded = vst_load_fonts(x_handle,0);
  442.  
  443.         return (TRUE);
  444.     }
  445.  
  446.     vqt_attributes(grhandle,attrib);
  447.     *id = attrib[0];
  448.  
  449.     if (vst_font(x_handle,*id)!=*id && fonts_loaded<0 && vq_gdos())
  450.         fonts_loaded = vst_load_fonts(x_handle,0);
  451.  
  452.     if (ap_gtype==1)
  453.     {
  454.         vst_font(x_handle,*id);
  455.         vst_point(x_handle,1,&dummy,&dummy,&dummy,&dummy);
  456.         vqt_attributes(x_handle,attrib);
  457.     }
  458.  
  459.     *height = attrib[7];
  460.     *type = 0;
  461.  
  462.     return(TRUE);
  463. }
  464.  
  465. void exit_gem()
  466. {
  467.     close_dials();
  468.  
  469.     if (fonts_loaded>=0)
  470.     {
  471.         vst_unload_fonts(x_handle,0);
  472.         fonts_loaded = FAIL;
  473.     }
  474.  
  475.     close_work(x_handle);
  476.     appl_exit();
  477. }
  478.  
  479. void set_images(IMAGES *images,int **on,int **off)
  480. {
  481.     reg IMAGE *im = images->image;
  482.     reg int i;
  483.     int dummy;
  484.  
  485.     if (big_img>=0)
  486.     {
  487.         for (i=0;i<images->count;i++,im++)
  488.         {
  489.             if (!big_img)
  490.             {
  491.                 if (im->lo_on)
  492.                     im->hi_on = im->lo_on;
  493.                 if (im->lo_off)
  494.                     im->hi_off = im->lo_off;
  495.             }
  496.             
  497.             vdi_trans(16,image_h,im->hi_on);
  498.             vdi_trans(16,image_h,im->hi_off);
  499.  
  500.             if (!big_img)
  501.             {
  502.                 if (!im->lo_on)
  503.                     scale_img(im->hi_on,16,16,DARK_SCALING,&dummy,&dummy);
  504.                 if (!im->lo_off)
  505.                     scale_img(im->hi_off,16,16,DARK_SCALING,&dummy,&dummy);
  506.             }
  507.         }
  508.  
  509.         if (images->count>0)
  510.         {
  511.             *on = images->image->hi_on;
  512.             if (off)
  513.                 *off = images->image->hi_off;
  514.         }
  515.     }
  516. }
  517.  
  518. void scale_image(OBJECT *obj,int mode)
  519. {
  520.     if (mode & SCALING)
  521.     {
  522.         int dummy;
  523.  
  524.         if (big_img>0)
  525.         {
  526.             obj->ob_x += ((gr_cw-(image_w>>1))*(obj->ob_width/gr_cw))>>1;
  527.             obj->ob_y += ((gr_ch-image_h)*(obj->ob_height/gr_ch))>>1;
  528.         }
  529.         else if ((unsigned char) obj->ob_type==G_ICON)
  530.         {
  531.             ICONBLK *icn = obj->ob_spec.iconblk;
  532.  
  533.             if (icn->ib_hicon>3)
  534.             {
  535.                 scale_img(icn->ib_pdata,icn->ib_wicon,icn->ib_hicon,mode,&dummy,&dummy);
  536.                 scale_img(icn->ib_pmask,icn->ib_wicon,icn->ib_hicon,mode,&dummy,&icn->ib_hicon);
  537.                 scale_coords(&icn->ib_xicon,&icn->ib_yicon);
  538.                 scale_coords(&icn->ib_xtext,&icn->ib_ytext);
  539.                 scale_coords(&icn->ib_xchar,&icn->ib_ychar);
  540.             }
  541.         }
  542.         else
  543.         {
  544.             BITBLK *blk = obj->ob_spec.bitblk;
  545.  
  546.             if (blk->bi_hl>3)
  547.             {
  548.                 scale_img((int *) blk->bi_pdata,blk->bi_wb<<3,blk->bi_hl,mode,&dummy,&blk->bi_hl);
  549.                 scale_coords(&blk->bi_x,&blk->bi_y);
  550.             }
  551.         }
  552.     }
  553. }
  554.  
  555. void scale_coords(int *w,int *h)
  556. {
  557.     *w = (((*w)*image_w)+7)>>4;
  558.     *h = (((*h)*image_h)+7)>>4;
  559. }
  560.  
  561. void scale_img(int *source,int w,int h,int mode,int *b_w,int *b_h)
  562. {
  563.     if (source && big_img<=0)
  564.     {
  565.         reg int pxy[8],dark = (mode & DARK_SCALING),vr_mode = (dark) ? 7 : 3;
  566.         reg MFDB image;
  567.         int n_w = w,n_h = h;
  568.  
  569.         scale_coords(&n_w,&n_h);
  570.         mfdb(&image,source,w,h,0,1);
  571.  
  572.         *b_w = n_w;
  573.         *b_h = n_h;
  574.  
  575.         if (n_h<h)
  576.         {
  577.             reg int y,n_y,l_y,flag=TRUE;
  578.  
  579.             pxy[0] = pxy[4] = l_y = n_y = y = 0;
  580.             pxy[2] = pxy[6] = w-1;
  581.  
  582.             for (;y<h;y++)
  583.             {
  584.                 if (n_y>=h || dark || y==(h-1))
  585.                 {
  586.                     pxy[1] = pxy[3] = y;
  587.                     pxy[5] = pxy[7] = l_y;
  588.                     vro_cpyfm(x_handle,(flag) ? 3 : vr_mode,pxy,&image,&image);
  589.                     if (n_y>=h)
  590.                     {
  591.                         n_y -= h;
  592.                         l_y++;
  593.                         flag = TRUE;
  594.                     }
  595.                     else
  596.                         flag = FALSE;
  597.                 }
  598.                 n_y += n_h;
  599.             }
  600.  
  601.             for (y=n_h-1;y<h;y++)
  602.             {
  603.                 pxy[1] = pxy[3] = pxy[5] = pxy[7] = y;
  604.                 vro_cpyfm(x_handle,0,pxy,&image,&image);
  605.             }
  606.             h = n_h;
  607.         }
  608.  
  609.         if (n_w<w)
  610.         {
  611.             reg int x,n_x,l_x,flag = TRUE;
  612.  
  613.             pxy[1] = pxy[5] = l_x = n_x = x = 0;
  614.             pxy[3] = pxy[7] = h-1;
  615.  
  616.             for (;x<w;x++)
  617.             {
  618.                 if (n_x>=w || dark || x==(w-1))
  619.                 {
  620.                     pxy[0] = pxy[2] = x;
  621.                     pxy[4] = pxy[6] = l_x;
  622.                     vro_cpyfm(x_handle,(flag) ? 3 : vr_mode,pxy,&image,&image);
  623.                     if (n_x>=w)
  624.                     {
  625.                         n_x -= w;
  626.                         l_x++;
  627.                         flag = TRUE;
  628.                     }
  629.                     else
  630.                         flag = FALSE;
  631.                 }
  632.                 n_x += n_w;
  633.             }
  634.  
  635.             for (x=n_w-1;x<w;x++)
  636.             {
  637.                 pxy[0] = pxy[2] = pxy[4] = pxy[6] = x;
  638.                 vro_cpyfm(x_handle,0,pxy,&image,&image);
  639.             }
  640.         }
  641.     }
  642. }
  643.  
  644. void vdi_trans(int w,int h,void *data)
  645. {
  646.     if (data)
  647.     {
  648.         reg MFDB src,dst;
  649.  
  650.         mfdb(&src,(int *) data,w,h,1,1);
  651.         mfdb(&dst,(int *) data,w,h,0,1);
  652.         vr_trnfm(x_handle,&src,&dst);
  653.     }
  654. }
  655.  
  656. void trans_image(OBJECT *obj)
  657. {
  658.     if ((unsigned char) obj->ob_type==G_ICON)
  659.     {
  660.         reg ICONBLK *icn=obj->ob_spec.iconblk;
  661.         vdi_trans(icn->ib_wicon,icn->ib_hicon,icn->ib_pmask);
  662.         vdi_trans(icn->ib_wicon,icn->ib_hicon,icn->ib_pdata);
  663.     }
  664.     else
  665.     {
  666.         reg BITBLK *img=obj->ob_spec.bitblk;
  667.         vdi_trans(img->bi_wb<<3,img->bi_hl,img->bi_pdata);
  668.     }
  669. }
  670.  
  671. void vrt_copy(int *image,PARMBLK *pb,int color,int selected)
  672. {
  673.     reg MFDB src;
  674.     reg int pxy[8],col[2],off = (big_img<0) ? 1:0;
  675.  
  676.     pxy[0] = pxy[1] = 0;
  677.     pxy[2] = image_w - 1;
  678.     pxy[3] = image_h - 1;
  679.     pxy[4] = pb->pb_x + (gr_cw-(image_w>>1)) + off;
  680.     pxy[5] = pb->pb_y + ((gr_ch-image_h)>>1) + off;
  681.     pxy[6] = pxy[4] + pxy[2];
  682.     pxy[7] = pxy[5] + pxy[3];
  683.  
  684.     if (selected)
  685.     {
  686.         col[1] = color;
  687.         col[0] = 0;
  688.     }
  689.     else
  690.     {
  691.         col[0] = color;
  692.         col[1] = 0;
  693.     }
  694.     mfdb(&src,image,16,image_h,0,1);
  695.     vrt_cpyfm(x_handle,1,pxy,&src,screen,col);
  696. }
  697.  
  698. void rsrc_calc(OBJECT *tree,int images)
  699. {
  700.     reg OBJECT *obj=tree;
  701.     reg int index=0;
  702.     for (;;)
  703.     {
  704.         rsrc_obfix(tree,index++);
  705.         if (obj->ob_x==0 && obj->ob_width>max_w)
  706.             obj->ob_width = max_w;
  707.         if (obj->ob_flags & LASTOB)
  708.             break;
  709.         obj++;
  710.     }
  711.     fix_objects(tree,images);
  712. }
  713.  
  714. void rsrc_init(int n_tree,int n_obs,int n_frstr,int n_frimg,int images,char **rs_strings,long *rs_frstr,BITBLK *rs_bitblk,
  715.                long *rs_frimg,ICONBLK *rs_iconblk,TEDINFO *rs_tedinfo,OBJECT *rs_object,OBJECT **rs_trindex,RS_IMDOPE *rs_imdope)
  716. {
  717.     reg OBJECT  *obj;
  718.     reg int tree,obi,index;
  719.  
  720.     for (obj = rs_object; obj < (rs_object+n_obs); obj++)
  721.     {
  722.         switch((unsigned char) obj->ob_type)
  723.         {
  724.         case G_TEXT:
  725.         case G_BOXTEXT:
  726.         case G_FTEXT:
  727.         case G_FBOXTEXT:
  728.             obj->ob_spec.tedinfo = &rs_tedinfo[obj->ob_spec.index];
  729.             obj->ob_spec.tedinfo->te_ptext = rs_strings[(int) obj->ob_spec.tedinfo->te_ptext];
  730.             obj->ob_spec.tedinfo->te_ptmplt = rs_strings[(int) obj->ob_spec.tedinfo->te_ptmplt];
  731.             obj->ob_spec.tedinfo->te_pvalid = rs_strings[(int) obj->ob_spec.tedinfo->te_pvalid];
  732.             break;
  733.         case G_BUTTON:
  734.         case G_STRING:
  735.         case G_TITLE:
  736.             obj->ob_spec.free_string = rs_strings[(int) obj->ob_spec.index];
  737.             break;
  738.         case G_IMAGE:
  739.             index = (int) obj->ob_spec.index,
  740.             rs_bitblk[index].bi_pdata = (void *) rs_imdope[(int) rs_bitblk[index].bi_pdata].image;
  741.             obj->ob_spec.bitblk = &rs_bitblk[index];
  742.             break;
  743.         case G_ICON:
  744.             index = (int) obj->ob_spec.index,
  745.             rs_iconblk[index].ib_pmask = rs_imdope[(int) rs_iconblk[index].ib_pmask].image;
  746.             rs_iconblk[index].ib_pdata = rs_imdope[(int) rs_iconblk[index].ib_pdata].image;
  747.             rs_iconblk[index].ib_ptext = rs_strings[(int) rs_iconblk[index].ib_ptext];
  748.             obj->ob_spec.iconblk = &rs_iconblk[index];
  749.             break;
  750.         }
  751.     }
  752.  
  753.     for (obi=0;obi<n_frstr;obi++)
  754.         rs_frstr[obi] = (long) rs_strings[(int) rs_frstr[obi]];
  755.  
  756.     for (obi=0;obi<n_frimg;obi++)
  757.     {
  758.         index = (int) rs_frimg[obi];
  759.         rs_bitblk[index].bi_pdata = (void *) rs_imdope[(int) rs_bitblk[index].bi_pdata].image;
  760.         rs_frimg[obi] = (long) &rs_bitblk[index];
  761.     }
  762.  
  763.     for (tree = 0; tree < n_tree; tree++)
  764.     {
  765.         rs_trindex[tree] = &rs_object[(int) rs_trindex[tree]];
  766.         rsrc_calc(rs_trindex[tree],images);
  767.     }
  768. }
  769.  
  770. void fix_objects(OBJECT *tree,int images)
  771. {
  772.     reg OBJECT *org=tree;
  773.     reg int xtype,modal,index=0;
  774.  
  775.     if ((images & TEST_SCALING) && (gr_cw!=8 || gr_ch!=16))
  776.         images |= SCALING;
  777.     else
  778.         images = NO_SCALING;
  779.  
  780.     do
  781.     {
  782.         tree++;index++;
  783.         switch((unsigned char) tree->ob_type)
  784.         {
  785.         case G_ICON:
  786.             {
  787.                 ICONBLK *icn = tree->ob_spec.iconblk;
  788.                 trans_image(tree);
  789.                 scale_image(tree,images);
  790.                 tree->ob_height = icn->ib_ytext+icn->ib_htext;
  791.             }
  792.             break;
  793.         case G_IMAGE:
  794.             trans_image(tree);
  795.             scale_image(tree,images);
  796.             tree->ob_height = tree->ob_spec.bitblk->bi_hl;
  797.             break;
  798.         default:
  799.             {
  800.                 modal = tree->ob_type & G_MODAL;
  801.                 xtype = (tree->ob_type ^ modal)>>8;
  802.                 switch(xtype)
  803.                 {
  804.                 case HEADER:
  805.                     {
  806.                         reg OBJECT *par = &org[ob_get_parent(org,index)];
  807.                         reg int frame = par->ob_spec.obspec.framesize;
  808.                         tree->ob_y -= (tree->ob_height>>1) + (1 - frame);
  809.                         if (frame<0)
  810.                             tree->ob_y++;
  811.                         if (par->ob_state & OUTLINED)
  812.                             tree->ob_y--;
  813.                     }
  814.                     break;
  815.                 case CHECKBOX:
  816.                 case CHKHOTKEY:
  817.                     if (xtype==CHKHOTKEY)
  818.                         tree->ob_type = G_CHK;
  819.                     else
  820.                         tree->ob_type = G_USERDEF;
  821.                     tree->ob_spec.userblk=&checkblk;
  822.                     break;
  823.                 case UNDERLINE:
  824.                     tree->ob_type = G_USERDEF;
  825.                     tree->ob_spec.userblk = &unlnblk;
  826.                     tree->ob_height = 1;
  827.                     break;
  828.                 case CYCLE_BUTTON:
  829.                     tree->ob_type = G_USERDEF;
  830.                     tree->ob_spec.userblk = &cycleblk;
  831.                     tree->ob_x--;
  832.                     tree->ob_y--;
  833.                     tree->ob_width = gr_dcw + 4;
  834.                     tree->ob_height = gr_ch + 4;
  835.                     break;
  836.                 case RADIO:
  837.                 case RBHOTKEY:
  838.                     if (xtype == RBHOTKEY)
  839.                         tree->ob_type = G_RB;
  840.                     else
  841.                         tree->ob_type = G_USERDEF;
  842.                     tree->ob_spec.userblk = &rbuttblk;
  843.                     break;
  844.                 case ARROW_LEFT:
  845.                 case ARROW_RIGHT:
  846.                 case ARROW_DOWN:
  847.                 case ARROW_UP:
  848.                     tree->ob_spec.userblk = &arrows;
  849.                     tree->ob_type = (xtype<<8)|G_USERDEF;
  850.                     break;
  851.                 case HOTKEY:
  852.                 case INDHOTKEY:
  853.                     {
  854.                         reg OBJECT *par = &org[ob_get_parent(org,index)];
  855.  
  856.                         if (xtype == INDHOTKEY)
  857.                             tree->ob_type = G_IND;
  858.                         else
  859.                             tree->ob_type = G_HOTKEY;
  860.  
  861.                         tree->ob_state &= 0x00ff;
  862.                         tree->ob_state |= _upper(tree->ob_spec.obspec.character)<<8;
  863.                         tree->ob_height = 1;
  864.                         tree->ob_spec.userblk = &hotkeyblk;
  865.  
  866.                         switch((unsigned char) par->ob_type)
  867.                         {
  868.                         case G_TEXT:
  869.                         case G_FTEXT:
  870.                             if (par->ob_spec.tedinfo->te_font==SMALL)
  871.                                 tree->ob_y = ((par->ob_height+gr_sh)>>1)+2;
  872.                             else
  873.                                 tree->ob_y = ((par->ob_height+gr_ch)>>1) - 1;
  874.                             break;
  875.                         case G_BOXTEXT:
  876.                         case G_FBOXTEXT:
  877.                             if (par->ob_spec.tedinfo->te_font==SMALL)
  878.                             {
  879.                                 tree->ob_y = ((par->ob_height+gr_sh)>>1)+2;
  880.                                 break;
  881.                             }
  882.                         case G_BUTTON:
  883.                         case G_BOXCHAR:
  884.                             if (par->ob_height==gr_ch)
  885.                             {
  886.                                 if (big_img==TRUE)
  887.                                 {
  888.                                     par->ob_height += 3;
  889.                                     par->ob_y--;
  890.                                 }
  891.                                 else
  892.                                     par->ob_height++;
  893.                             }
  894.  
  895.                             tree->ob_y = (par->ob_height>>1)+(gr_ch>>1);
  896.                             break;
  897.                         default:
  898.                             tree->ob_y = gr_ch - 1;
  899.                         }
  900.                     }
  901.                     break;
  902.                 case FLYDIAL:
  903.                     tree->ob_spec.userblk = &flyblk;
  904.                     tree->ob_type = G_FLY;
  905.  
  906.                     tree->ob_x = org->ob_width - gr_dcw - 1;
  907.                     tree->ob_y = -3;
  908.                     tree->ob_width = gr_dcw + 4;
  909.                     tree->ob_height = gr_ch + 4;
  910.                     break;
  911.                 case TXTDEFAULT:
  912.                     tree->ob_flags |= INDDEFAULT;
  913.                     break;
  914.                 case ATTR_TEXT:
  915.                     {
  916.                         reg char *string = NULL;
  917.                         reg int font,color,center;
  918.  
  919.                         switch ((unsigned char) tree->ob_type)
  920.                         {
  921.                         case G_STRING:
  922.                             string    = tree->ob_spec.free_string;
  923.                             color    = BLACK;
  924.                             font    = IBM;
  925.                             center  = 0;
  926.                             break;
  927.                         case G_TEXT:
  928.                             {
  929.                                 TEDINFO *ted = tree->ob_spec.tedinfo;
  930.  
  931.                                 string    = ted->te_ptext;
  932.                                 font    = ted->te_font;
  933.                                 color    = ted->te_color;
  934.                                 center  = ted->te_just;
  935.                             }
  936.                             break;
  937.                         }
  938.  
  939.                         if (string)
  940.                         {
  941.                             reg V_LIST *list = &v_list;
  942.                             reg V_TEXT *v_text;
  943.  
  944.                             for (;;)
  945.                             {
  946.                                 if (list->index<128)
  947.                                 {
  948.                                     v_text = list->start + list->index;
  949.                                     list->index++;
  950.                                     break;
  951.                                 }
  952.                                 else if (list->next)
  953.                                     list = list->next;
  954.                                 else
  955.                                 {
  956.                                     list->next = (V_LIST *) calloc(1,sizeof(V_LIST));
  957.                                     if ((list = list->next)!=NULL)
  958.                                     {
  959.                                         if ((v_text = list->start = (V_TEXT *) calloc(128,sizeof(V_TEXT)))==NULL)
  960.                                             Mfree(list);
  961.                                     }
  962.                                     else
  963.                                         v_text = NULL;
  964.                                     break;
  965.                                 }
  966.                             }
  967.  
  968.                             if (v_text)
  969.                             {
  970.                                 v_text->text_blk.ub_code = draw_text;
  971.                                 v_text->text_blk.ub_parm = (long) v_text;
  972.  
  973.                                 v_text->font    = font;
  974.                                 v_text->color    = color;
  975.                                 v_text->center    = center;
  976.                                 v_text->string    = string;
  977.  
  978.                                 tree->ob_type    = (ATTR_TEXT<<8)|G_USERDEF;
  979.                                 tree->ob_spec.userblk = &v_text->text_blk;
  980.                             }
  981.                         }
  982.                     }
  983.                     break;
  984.                 default:
  985.                     if (tree->ob_type==G_STRING && (tree->ob_state & DISABLED))
  986.                         if (tree->ob_spec.free_string[0]=='-')
  987.                         {
  988.                             tree->ob_type = G_USERDEF;
  989.                             tree->ob_spec.userblk = &menublk;
  990.                         }
  991.                 }
  992.                 tree->ob_type |= modal;
  993.             }
  994.         }
  995.     }
  996.     while(!(tree->ob_flags & LASTOB));
  997. }
  998.  
  999. void find_fly(DIAINFO *info)
  1000. {
  1001.     reg OBJECT *tree=info->di_tree;
  1002.     reg int type;
  1003.  
  1004.     info->di_fly = FALSE;
  1005.     do
  1006.     {
  1007.         tree++;
  1008.         type = tree->ob_type & (~G_MODAL);
  1009.         if (type==G_FLY || (type>>8)==USERFLY)
  1010.         {
  1011.             tree->ob_flags &= ~HIDETREE;
  1012.             switch (info->di_flag)
  1013.             {
  1014.             case OPENED:
  1015.                 tree->ob_state |= DISABLED;
  1016.                 break;
  1017.             case WINDOW:
  1018.             case WIN_MODAL:
  1019.                 if (type==G_FLY)
  1020.                     tree->ob_flags |= HIDETREE;
  1021.                 break;
  1022.             case FLYING:
  1023.                 tree->ob_state &= ~DISABLED;
  1024.                 info->di_fly = TRUE;
  1025.                 break;
  1026.             }
  1027.             break;
  1028.         }
  1029.     }
  1030.     while (!(tree->ob_flags & LASTOB));
  1031. }
  1032.  
  1033. void dial_center(OBJECT *tree,boolean center,int xy,int wh)
  1034. {
  1035.     int x,y,w,h;
  1036.  
  1037.     switch (center)
  1038.     {
  1039.     case TRUE:
  1040.         {
  1041.             _mouse_pos(&x,&y);
  1042.             tree->ob_x = x - (tree->ob_width>>1);
  1043.             tree->ob_y = y - (tree->ob_height>>1);
  1044.             break;
  1045.         }
  1046.     case FAIL:
  1047.         if (tree->ob_x>desk.g_x && tree->ob_y>desk.g_y)
  1048.             break;
  1049.     case FALSE:
  1050.         {
  1051.             INFOVSCR *vscr;
  1052.  
  1053.             form_center(tree,&x,&y,&w,&h);
  1054.             if (get_cookie(COOKIE_VSCR,(long *) &vscr) && (vscr->cookie==COOKIE_XBRA))
  1055.             {
  1056.                 tree->ob_x = vscr->x + ((vscr->w - w)>>1);
  1057.                 tree->ob_y = vscr->y + ((vscr->h - h)>>1);
  1058.             }
  1059.         }
  1060.     }
  1061.     dial_pos(tree,xy,wh);
  1062. }
  1063.  
  1064. void dial_pos(OBJECT *tree,int xy,int wh)
  1065. {
  1066.     reg int d;
  1067.  
  1068.     if ((d=(tree->ob_x + tree->ob_width + wh)) > clip.v_x2)
  1069.         tree->ob_x -= d - clip.v_x2;
  1070.  
  1071.     if (dial_round)
  1072.     {
  1073.         tree->ob_x &= 0xFFF8;
  1074.         if (tree->ob_x < (clip.v_x1+xy))
  1075.             tree->ob_x = (clip.v_x1+xy+7) & 0xFFF8;
  1076.     }
  1077.     else
  1078.         Max(&tree->ob_x,clip.v_x1+xy);
  1079.  
  1080.     if ((d=(tree->ob_y + tree->ob_height + wh)) > clip.v_y2)
  1081.         tree->ob_y -= d - clip.v_y2;
  1082.     Max(&tree->ob_y,clip.v_y1+xy);
  1083. }
  1084.  
  1085. void open_flydialog(OBJECT *tree, DIAINFO *info, boolean center,boolean box)
  1086. {
  1087.     if (call_func && dinfo->di_ed_obj>0)
  1088.         edit_off();
  1089.  
  1090.     _beg_ctrl();
  1091.     dial_center(tree,center,4,4);
  1092.  
  1093.     if ((tree->ob_width<=desk.g_w) && (tree->ob_height<=desk.g_h))
  1094.     {
  1095.         long len;
  1096.  
  1097.         mfdb(&info->di_mfdb,NULL,tree->ob_width+6,tree->ob_height+6,0,planes);
  1098.         info->di_length = len = mfdb_size(&info->di_mfdb);
  1099.  
  1100.         if ((long) Malloc(-1l)>(len+4096l))
  1101.         {
  1102.             if ((info->di_mem = (long) Malloc(len+256l))>0l)
  1103.             {
  1104.                 info->di_mfdb.fd_addr    = (int *) ((info->di_mem & 0xfffffffel) + 2);
  1105.                 info->di_flag = FLYING;
  1106.                 _bitblt(tree,&info->di_mfdb,TRUE);
  1107.                 goto draw_dialog;
  1108.             }
  1109.         }
  1110.     }
  1111.     info->di_mfdb.fd_addr = NULL;
  1112.     info->di_flag = OPENED;
  1113.     form_dial(FMD_START,0,0,0,0,tree->ob_x-3,tree->ob_y-3,tree->ob_width+6,tree->ob_height+6);
  1114.  
  1115.     draw_dialog:
  1116.     info->di_tree=tree;
  1117.     find_fly(info);
  1118.     if (box)
  1119.         graf_growbox (max_w>>1,max_h>>1,1,1,tree->ob_x,tree->ob_y,tree->ob_width,tree->ob_height);
  1120.     graf_mouse(ARROW,NULL);
  1121.     objc_draw(tree,ROOT,MAX_DEPTH,desk.g_x,desk.g_y,desk.g_w,desk.g_h);
  1122.     _dia_list[_dia_len++] = info;
  1123. }
  1124.  
  1125. void close_dialog(DIAINFO *info,boolean box)
  1126. {
  1127.     OBJECT    *tree=info->di_tree;
  1128.  
  1129.     graf_mouse(ARROW,NULL);
  1130.  
  1131.     switch (info->di_flag)
  1132.     {
  1133.     case WINDOW:
  1134.     case WIN_MODAL:
  1135.         {
  1136.             reg int i;
  1137.  
  1138.             if (box)
  1139.                 graf_shrinkbox (max_w>>1,max_h>>1,1,1,tree->ob_x,tree->ob_y,tree->ob_width,tree->ob_height);
  1140.  
  1141.             if (!ac_close && wind_close(info->di_handle))
  1142.                 wind_delete(info->di_handle);
  1143.  
  1144.             if (info->di_flag==WIN_MODAL && _app && menu)
  1145.             {
  1146.                 for (i=win_len;--i>=0;)
  1147.                     if (win_list[i]->di_flag==WIN_MODAL && win_list[i]!=info)
  1148.                         break;
  1149.                 if (i<0)
  1150.                     menu_enable(menu,TRUE,TRUE);
  1151.             }
  1152.  
  1153.             for (i=0;i<win_len;i++)
  1154.                 if (win_list[i]==info)
  1155.                     break;
  1156.             win_len--;
  1157.             for (;i<win_len;i++)
  1158.                 win_list[i] = win_list[i+1];
  1159.             w_init = FAIL;
  1160.         }
  1161.         break;
  1162.     case OPENED:
  1163.     case FLYING:
  1164.         {
  1165.             if (box)
  1166.                 graf_shrinkbox (max_w>>1,max_h>>1,1,1,tree->ob_x,tree->ob_y,tree->ob_width,tree->ob_height);
  1167.  
  1168.             if (info->di_flag == OPENED)
  1169.                 form_dial(FMD_FINISH,0,0,0,0,tree->ob_x-3,tree->ob_y-3,tree->ob_width+6, tree->ob_height+6);
  1170.             else
  1171.             {
  1172.                 _bitblt(tree,&info->di_mfdb,FALSE);
  1173.                 Mfree((void *) info->di_mem);
  1174.             }
  1175.             _end_ctrl();
  1176.             _dia_len--;
  1177.             w_init = FAIL;
  1178.         }
  1179.     }
  1180.  
  1181.     memset(info,0,sizeof(DIAINFO));
  1182. }
  1183.  
  1184. #ifdef DEBUG
  1185.  
  1186. void check_hotkeys(OBJECT *tree)
  1187. {
  1188.     reg OBJECT *obj=tree;
  1189.     reg char hotkeys[128],*p=hotkeys,c;
  1190.     reg int index = 0;
  1191.     char msg[128];
  1192.  
  1193.     do
  1194.     {
  1195.         obj++;
  1196.         index++;
  1197.  
  1198.         switch (obj->ob_type & (~G_MODAL))
  1199.         {
  1200.         case G_IND:
  1201.         case G_HOTKEY:
  1202.             c = obj->ob_state>>8;
  1203.             if (c && !(tree[ob_get_parent(tree,index)].ob_flags & HIDETREE))
  1204.             {
  1205.                 *p = '\0';
  1206.                 if (strchr(hotkeys,c)==NULL)
  1207.                     *p++ = c;
  1208.                 else
  1209.                 {
  1210.                     sprintf(msg,HOTKEY_ERR,c,index);
  1211.                     form_alert(1,msg);
  1212.                 }
  1213.             }
  1214.         }
  1215.     }
  1216.     while (!(obj->ob_flags & LASTOB));
  1217. }
  1218.  
  1219. #endif
  1220.  
  1221. boolean open_dialog(OBJECT *tree,DIAINFO *info,char *win_name,boolean center,boolean box,int mode)
  1222. {
  1223.     reg OBJECT *obj = tree;
  1224.     reg int i,modal;
  1225.  
  1226.     memset((void *) info,0,sizeof(DIAINFO));
  1227.     for (i=0;i<win_len;i++)
  1228.         if (win_list[i]->di_flag==WIN_MODAL)
  1229.         {
  1230.             mode |= MODAL;
  1231.             break;
  1232.         }
  1233.  
  1234.     do
  1235.     {
  1236.         obj++;
  1237.         modal = obj->ob_type & G_MODAL;
  1238.         if (((obj->ob_type ^ modal)>>8)==HEADER)
  1239.         {
  1240.             switch((unsigned char) obj->ob_type)
  1241.             {
  1242.             case G_TEXT:
  1243.             case G_BOXTEXT:
  1244.                 if (dial_tframe)
  1245.                     obj->ob_type = G_BOXTEXT|modal;
  1246.                 else
  1247.                     obj->ob_type = G_TEXT|modal;
  1248.                 goto _set_title;
  1249.             case G_FTEXT:
  1250.             case G_FBOXTEXT:
  1251.                 if (dial_tframe)
  1252.                     obj->ob_type = G_FBOXTEXT|modal;
  1253.                 else
  1254.                     obj->ob_type = G_FTEXT|modal;
  1255.                 _set_title:
  1256.                 obj->ob_type |= (HEADER<<8);
  1257.                 obj->ob_spec.tedinfo->te_font = (dial_tsmall) ? SMALL : IBM;
  1258.                 obj->ob_spec.tedinfo->te_just = (dial_tframe) ? 2 : 0;
  1259.                 break;
  1260.             }
  1261.         }
  1262.     }
  1263.     while (!(obj->ob_flags & LASTOB));
  1264.  
  1265.     tree->ob_state |= OUTLINED;
  1266.     tree->ob_state &= ~SHADOWED;
  1267.  
  1268.     tree->ob_spec.obspec.interiorcol = dial_color;
  1269.     tree->ob_spec.obspec.fillpattern = dial_pattern;
  1270.     tree->ob_spec.obspec.framecol     = 1;
  1271.  
  1272.     if (!(mode & WIN_DIAL) || _dia_len || !open_windialog(tree,info,win_name,mode,center,box))
  1273.         if (mode & FLY_DIAL)
  1274.         {
  1275.             obj = tree;    
  1276.             do
  1277.             {
  1278.                 obj++;
  1279.                 if (obj->ob_type & G_MODAL)
  1280.                     obj->ob_flags &= ~HIDETREE;
  1281.             }
  1282.             while (!(obj->ob_flags & LASTOB));
  1283.             open_flydialog(tree,info,center,box);
  1284.         }
  1285.  
  1286.     if (info->di_flag>=WINDOW)
  1287.     {
  1288.         obj = tree;    
  1289.         do
  1290.         {
  1291.             obj++;
  1292.             if (obj->ob_type & G_MODAL)
  1293.             {
  1294.                 if (info->di_flag==WINDOW)
  1295.                     obj->ob_flags |= HIDETREE;
  1296.                 else
  1297.                     obj->ob_flags &= ~HIDETREE;
  1298.             }
  1299.         }
  1300.         while (!(obj->ob_flags & LASTOB));
  1301.     }
  1302.  
  1303.     if (info->di_flag>CLOSED)
  1304.     {
  1305.     #ifdef DEBUG
  1306.         check_hotkeys(tree);
  1307.     #endif
  1308.         w_init = TRUE;
  1309.         return(TRUE);
  1310.     }
  1311.     else
  1312.         return(FALSE);
  1313. }
  1314.  
  1315. boolean open_windialog(OBJECT *tree,DIAINFO *info,char *win_name,int mode,boolean center,boolean box)
  1316. {
  1317.     if (win_len<128)
  1318.     {
  1319.         int typ = WIN_ELEMENTE;
  1320.  
  1321.         if (!(mode & MODAL))
  1322.             typ |= CLOSER;
  1323.  
  1324.         if (!(mode & NO_ICONIFY))
  1325.             typ |= SMALLER;
  1326.  
  1327.         info->di_handle = wind_create(typ,desk.g_x,desk.g_y,desk.g_w,desk.g_h);
  1328.         if (info->di_handle>0)
  1329.         {
  1330.             int x,y,w,h;
  1331.  
  1332.             if (call_func && dinfo->di_ed_obj>0)
  1333.                 edit_off();
  1334.  
  1335.             if (mode & FRAME)
  1336.             {
  1337.                 info->di_xy_off = 3;
  1338.                 info->di_wh_off = 5;
  1339.             }
  1340.             else
  1341.             {
  1342.                 info->di_xy_off = -2;
  1343.                 info->di_wh_off = -4;
  1344.                 tree->ob_state &= ~OUTLINED;
  1345.             }
  1346.  
  1347.             dial_center(tree,center,0,info->di_wh_off-info->di_xy_off+3);
  1348.             wind_calc(WC_BORDER,WIN_ELEMENTE,tree->ob_x-info->di_xy_off,tree->ob_y-info->di_xy_off,
  1349.                       tree->ob_width+info->di_wh_off,tree->ob_height+info->di_wh_off,&x,&y,&w,&h);
  1350.  
  1351.             if (dial_round)
  1352.                 while (x<clip.v_x1)
  1353.                 {
  1354.                     tree->ob_x += 8;
  1355.                     x += 8;
  1356.                 }
  1357.             else if (x<clip.v_x1)
  1358.             {
  1359.                 tree->ob_x = clip.v_x1 - x;
  1360.                 x = clip.v_x1;
  1361.             }
  1362.  
  1363.             if (y<clip.v_y1)
  1364.             {
  1365.                 tree->ob_y += clip.v_y1 - y;
  1366.                 y = clip.v_y1;
  1367.             }
  1368.  
  1369.             if (mode & MODAL)
  1370.             {
  1371.                 if (_app && menu)
  1372.                     menu_enable(menu,FALSE,TRUE);
  1373.                 info->di_flag = WIN_MODAL;
  1374.             }
  1375.             else
  1376.                 info->di_flag = WINDOW;
  1377.  
  1378.             info->di_mfdb.fd_addr = NULL;
  1379.             info->di_tree = tree;
  1380.             find_fly(info);
  1381.             if (box)
  1382.                 graf_growbox(max_w>>1,max_h>>1,1,1,tree->ob_x,tree->ob_y,tree->ob_width,tree->ob_height);
  1383.             info->di_title = win_name;
  1384.             wind_set(info->di_handle,WF_NAME,win_name);
  1385.             if (_back_win && _bevent)
  1386.                 wind_set(info->di_handle,WF_BEVENT,1);
  1387.             graf_mouse(ARROW,NULL);
  1388.             wind_open(info->di_handle,x,y,w,h);
  1389.             win_list[win_len++]=info;
  1390.             return(TRUE);
  1391.         }
  1392.     }
  1393.     return(FALSE);
  1394. }
  1395.  
  1396. void move_dialog(DIAINFO *info,GRECT *area)
  1397. {
  1398.     reg OBJECT *tree = info->di_tree;
  1399.     reg int *rect = (int *) area;
  1400.     int d;
  1401.  
  1402.     if (!info->di_iconified)
  1403.     {
  1404.         wind_calc(WC_WORK,WIN_ELEMENTE,rect[0],rect[1],rect[2],rect[3],&tree->ob_x,&tree->ob_y,&d,&d);
  1405.         tree->ob_x += info->di_xy_off;
  1406.         tree->ob_y += info->di_xy_off;
  1407.  
  1408.         if (dial_round)
  1409.         {
  1410.             tree->ob_x &= 0xFFF8;
  1411.             wind_calc(WC_BORDER,WIN_ELEMENTE,tree->ob_x-info->di_xy_off,tree->ob_y-info->di_xy_off,
  1412.                       tree->ob_width+info->di_wh_off,tree->ob_height+info->di_wh_off,rect,rect+1,rect+2,rect+3);
  1413.  
  1414.             while (rect[0]<clip.v_x1)
  1415.             {
  1416.                 tree->ob_x += 8;
  1417.                 rect[0] += 8;
  1418.             }
  1419.         }
  1420.     }
  1421.  
  1422.     wind_set(info->di_handle,WF_CURRXYWH,rect[0],rect[1],rect[2],rect[3]);
  1423. }
  1424.  
  1425. void redraw_iconified(int handle,OBJECT *icon,GRECT *area)
  1426. {
  1427.     rc_sc_clear(area);
  1428.  
  1429.     if (icon!=NULL)
  1430.     {
  1431.         GRECT win;
  1432.  
  1433.         wind_get(handle,WF_WORKXYWH,&win.g_x,&win.g_y,&win.g_w,&win.g_h);
  1434.  
  1435.         icon->ob_x = win.g_x + ((win.g_w - icon->ob_width)>>1);
  1436.         icon->ob_y = win.g_y + ((win.g_h - icon->ob_height)>>1);
  1437.         objc_draw(icon,0,MAX_DEPTH,area->g_x,area->g_y,area->g_w,area->g_h);
  1438.     }
  1439. }
  1440.  
  1441. void redraw_dialog(DIAINFO *info,GRECT *area)
  1442. {
  1443.     GRECT work;
  1444.     reg OBJECT *tree=info->di_tree;
  1445.     reg boolean cursor=FALSE,clp=FALSE,icon=info->di_iconified;
  1446.     reg int    pxy[4],index;
  1447.  
  1448.     redraw++;
  1449.     wind_update(BEG_UPDATE);
  1450.  
  1451.     if (info->di_ed_obj>0)
  1452.     {
  1453.         if (info->di_cursor && win_topped(info))
  1454.         {
  1455.             edit_off();
  1456.             index = info->di_ed_index;
  1457.             cursor = TRUE;
  1458.         }
  1459.     }
  1460.  
  1461.     wind_get(info->di_handle,WF_FIRSTXYWH,&work.g_x,&work.g_y,&work.g_w,&work.g_h);
  1462.     while (work.g_w>0 && work.g_h>0)
  1463.     {
  1464.         if (rc_intersect(area,&work))
  1465.         {
  1466.             if (clp==FALSE)
  1467.             {
  1468.                 graf_mouse(M_OFF,NULL);
  1469.                 clp = TRUE;
  1470.             }
  1471.  
  1472.             if (icon)
  1473.                 redraw_iconified(info->di_handle,iconified,&work);
  1474.             else
  1475.             {
  1476.                 rc_grect_to_array(&work,pxy);
  1477.                 _set_clip(pxy);
  1478.                 objc_draw(tree,ROOT,MAX_DEPTH,work.g_x,work.g_y,work.g_w,work.g_h);
  1479.             }
  1480.         }
  1481.         wind_get(info->di_handle,WF_NEXTXYWH,&work.g_x,&work.g_y,&work.g_w,&work.g_h);
  1482.     }
  1483.  
  1484.     if (clp)
  1485.         _set_clip((int *) &clip);
  1486.  
  1487.     if (cursor)
  1488.         edit_pos(index,TRUE);
  1489.  
  1490.     if (clp)
  1491.         graf_mouse(M_ON,NULL);
  1492.     wind_update(END_UPDATE);
  1493.  
  1494.     redraw=0;
  1495. }
  1496.  
  1497. int cdecl draw_underline(PARMBLK *pb)
  1498. {
  1499.     reg OBJECT *tree = pb->pb_tree,*obj = tree + pb->pb_obj;
  1500.     reg int d,x1,x2,disabled,type = ((obj->ob_type & (~G_MODAL))==G_USERDEF);
  1501.  
  1502.     if (type)
  1503.     {
  1504.         _vdi_attr(MD_REPLACE,(d=(int) (pb->pb_parm>>8)),(char) pb->pb_parm);
  1505.         disabled = 0;
  1506.     }
  1507.     else
  1508.     {
  1509.         disabled = tree[ob_get_parent(tree,pb->pb_obj)].ob_state;
  1510.         _vdi_attr((disabled & SELECTED) ? MD_XOR : MD_REPLACE,d=1,(char) (pb->pb_parm));
  1511.  
  1512.         if ((disabled &= DISABLED)!=0)
  1513.             vsl_type(x_handle,7);
  1514.     }
  1515.  
  1516.     if (type && dial_title)
  1517.     {
  1518.         x1 = tree->ob_x + gr_cw;
  1519.         x2 = tree->ob_x + tree->ob_width - gr_cw - 1;
  1520.     }
  1521.     else
  1522.     {
  1523.         x1 = pb->pb_x;
  1524.         x2 = pb->pb_x + pb->pb_w - 1;
  1525.     }
  1526.     _line(x1,pb->pb_y,x2,pb->pb_y);
  1527.  
  1528.     if (type && (obj->ob_state & OUTLINED))
  1529.     {
  1530.         d += d;
  1531.         _line(x1,pb->pb_y+d,x2,pb->pb_y+d);
  1532.     }
  1533.  
  1534.     if (disabled)
  1535.         vsl_type(x_handle,1);
  1536.     return(0);
  1537. }
  1538.  
  1539. int cdecl draw_box(PARMBLK *pb)
  1540. {
  1541.     reg OBJECT *obj = &pb->pb_tree[pb->pb_obj];
  1542.     reg int disabled = ((pb->pb_tree[obj->ob_next].ob_state)|obj->ob_state) & DISABLED;
  1543.  
  1544.     if (big_img<0)
  1545.     {
  1546.         reg int color = (int) pb->pb_parm;
  1547.         reg int x = pb->pb_x+1,y = pb->pb_y+1,w = pb->pb_w-3,h=pb->pb_w-3;
  1548.  
  1549.         _vdi_attr(MD_REPLACE,1,color);
  1550.         _bar(x,y,w,h,0,color);
  1551.  
  1552.         if (pb->pb_currstate & SELECTED)
  1553.         {
  1554.             _line(x,y,x+w,y+h);
  1555.             _line(x+w,y,x,y+h);
  1556.         }
  1557.     }
  1558.     else if (pb->pb_currstate & SELECTED)
  1559.         vrt_copy(box_on,pb,(int) pb->pb_parm,0);
  1560.     else
  1561.         vrt_copy(box_off,pb,(int) pb->pb_parm,0);
  1562.     return(disabled);
  1563. }
  1564.  
  1565. int cdecl draw_cyclebutton(PARMBLK *pb)
  1566. {
  1567.     reg int color = (int) pb->pb_parm,w,h;
  1568.  
  1569.     w = gr_dcw;
  1570.     h = gr_ch;
  1571.     if (big_img<0)
  1572.         w--;
  1573.  
  1574.     pb->pb_x++;
  1575.     pb->pb_y++;
  1576.     pb->pb_w = w;
  1577.     pb->pb_h = h;
  1578.  
  1579.     _vdi_attr(MD_REPLACE,1,color);
  1580.     _bar(pb->pb_x+2,pb->pb_y+2,w,h,1,color);
  1581.  
  1582.     if (big_img<0)
  1583.     {
  1584.         _bar(pb->pb_x-1,pb->pb_y-1,w+1,h+1,0,color);
  1585.         v_set_text(ibm_font_id,ibm_font,color,NULL);
  1586.         v_gtext(x_handle,pb->pb_x+(gr_cw>>1),pb->pb_y,"\x02");
  1587.         if (pb->pb_currstate & SELECTED)
  1588.             rc_sc_invert((GRECT *) &pb->pb_x);
  1589.     }
  1590.     else
  1591.     {
  1592.         _rectangle(pb->pb_x-1,pb->pb_y-1,pb->pb_x+w,pb->pb_y+h);
  1593.         vrt_copy(cycle_but,pb,color,pb->pb_currstate & SELECTED);
  1594.     }
  1595.  
  1596.     return(pb->pb_currstate & DISABLED);
  1597. }
  1598.  
  1599. int cdecl draw_radiobutton(PARMBLK *pb)
  1600. {
  1601.     reg OBJECT *obj = &pb->pb_tree[pb->pb_obj];
  1602.     reg int disabled = ((pb->pb_tree[obj->ob_next].ob_state)|obj->ob_state) & DISABLED;
  1603.  
  1604.     if (big_img<0)
  1605.     {
  1606.         reg int color = (int) pb->pb_parm;
  1607.  
  1608.         _vdi_attr(MD_REPLACE,1,color);
  1609.         _bar(pb->pb_x+1,pb->pb_y+1,pb->pb_w-3,pb->pb_h-3,0,color);
  1610.         if ((pb->pb_currstate & SELECTED) && !disabled)
  1611.             _bar(pb->pb_x+4,pb->pb_y+4,pb->pb_w-9,pb->pb_h-9,1,color);
  1612.     }
  1613.     else if (pb->pb_currstate & SELECTED)
  1614.         vrt_copy(radio_on,pb,(int) pb->pb_parm,0);
  1615.     else
  1616.         vrt_copy(radio_off,pb,(int) pb->pb_parm,0);
  1617.     return(disabled);
  1618. }
  1619.  
  1620. int cdecl draw_arrows(PARMBLK *pb)
  1621. {
  1622.     reg int type = (pb->pb_tree[pb->pb_obj].ob_type & (~G_MODAL))>>8,color = (int) pb->pb_parm;
  1623.  
  1624.     _vdi_attr(MD_REPLACE,1,color);
  1625.     if (big_img<0)
  1626.     {
  1627.         _bar(pb->pb_x-1,pb->pb_y-1,gr_dcw+1,gr_ch+1,0,(pb->pb_currstate & OUTLINED) ? color : 0);
  1628.         v_set_text(ibm_font_id,ibm_font,color,NULL);
  1629.         v_gtext(x_handle,pb->pb_x+(gr_cw>>1),pb->pb_y,c_arrow[type-ARROW_LEFT]);
  1630.         if (pb->pb_currstate & SELECTED)
  1631.             rc_sc_invert((GRECT *) &pb->pb_x);
  1632.     }
  1633.     else
  1634.     {
  1635.         reg int *but,*sel;
  1636.  
  1637.         if (pb->pb_currstate & OUTLINED)
  1638.             _rectangle(pb->pb_x-1,pb->pb_y-1,pb->pb_x+gr_dcw,pb->pb_y+gr_ch);
  1639.  
  1640.         switch (type)
  1641.         {
  1642.         case ARROW_UP:
  1643.             but = arrow_up;
  1644.             sel = arrow_up_sel;
  1645.             break;
  1646.         case ARROW_DOWN:
  1647.             but = arrow_down;
  1648.             sel = arrow_down_sel;
  1649.             break;
  1650.         case ARROW_LEFT:
  1651.             but = arrow_left;
  1652.             sel = arrow_left_sel;
  1653.             break;
  1654.         default:
  1655.             but = arrow_right;
  1656.             sel = arrow_right_sel;
  1657.             break;
  1658.         }
  1659.     
  1660.         if (pb->pb_currstate & SELECTED)
  1661.         {
  1662.             if (sel)
  1663.                 vrt_copy(sel,pb,color,0);
  1664.             else
  1665.                 vrt_copy(but,pb,color,1);
  1666.         }
  1667.         else
  1668.             vrt_copy(but,pb,color,0);
  1669.     }
  1670.     return(pb->pb_currstate & DISABLED);
  1671. }
  1672.  
  1673. int cdecl draw_fly(PARMBLK *pb)
  1674. {
  1675.     reg int pxy[6],w=pb->pb_w-1,h=pb->pb_h-1;
  1676.  
  1677.     _vdi_attr(MD_REPLACE,1,BLACK);
  1678.     _bar(pb->pb_x,pb->pb_y,w,h,0,BLACK);
  1679.  
  1680.     if (pb->pb_tree->ob_state & OUTLINED)
  1681.     {
  1682.         pxy[0] = pb->pb_x + 3;
  1683.         pxy[3] = pxy[1] = pb->pb_y + 3;
  1684.         pxy[4] = pxy[2] = pb->pb_x + pb->pb_w - 4;
  1685.         pxy[5] = pb->pb_y + pb->pb_h - 4;
  1686.         v_pline(x_handle,3,pxy);
  1687.  
  1688.         if (pb->pb_tree->ob_spec.obspec.framesize!=1)
  1689.         {
  1690.             if (big_img>0)
  1691.                 pxy[0]++;
  1692.             else
  1693.                 pxy[0] += 2;
  1694.             pxy[1]++;
  1695.             pxy[2]--;
  1696.             pxy[3]++;
  1697.             pxy[4]--;
  1698.             if (big_img>0)
  1699.                 pxy[5]--;
  1700.             v_pline(x_handle,3,pxy);
  1701.         }
  1702.     }
  1703.  
  1704.     _line(pb->pb_x,pb->pb_y,pb->pb_x + w,pb->pb_y + h);
  1705.     return(pb->pb_currstate & ~SELECTED);
  1706. }
  1707.  
  1708. int cdecl draw_text(PARMBLK *pb)
  1709. {
  1710.     reg V_TEXT *text = (V_TEXT *) pb->pb_parm;
  1711.     reg int state = pb->pb_tree[pb->pb_obj].ob_state,effect = 0,color = text->color,x=pb->pb_x,y=pb->pb_y;
  1712.     reg int pxy[8];
  1713.  
  1714.     v_set_mode(MD_TRANS);
  1715.     if (text->font==SMALL)
  1716.         v_set_text(small_font_id,small_font,color,NULL);
  1717.     else
  1718.         v_set_text(ibm_font_id,ibm_font,color,NULL);
  1719.  
  1720.     if (state & SELECTED)
  1721.         effect |= 1;
  1722.     if (state & CHECKED)
  1723.         effect |= 8;
  1724.     if (state & CROSSED)
  1725.         effect |= 4;
  1726.     if (state & DISABLED)
  1727.         effect |= 2;
  1728.     if (state & OUTLINED)
  1729.         effect |= 16;
  1730.  
  1731.     if (state & SHADOWED)
  1732.     {
  1733.         vst_effects(x_handle,effect|2);
  1734.  
  1735.         vqt_extent(x_handle,(char *) text->string,&pxy[0]);
  1736.         switch (text->center)
  1737.         {
  1738.         case TE_RIGHT:
  1739.             x += pb->pb_w - pxy[4];
  1740.             break;
  1741.         case TE_CNTR:
  1742.             x += (pb->pb_w - pxy[4])>>1;
  1743.         }
  1744.         y += (pb->pb_h - pxy[5])>>1;
  1745.  
  1746.         v_gtext(x_handle,x+2,y+2,(char *) text->string);
  1747.         vst_effects(x_handle,effect);
  1748.     }
  1749.     else
  1750.     {
  1751.         vst_effects(x_handle,effect);
  1752.  
  1753.         vqt_extent(x_handle,(char *) text->string,&pxy[0]);
  1754.         switch (text->center)
  1755.         {
  1756.         case TE_RIGHT:
  1757.             x += pb->pb_w - pxy[4];
  1758.             break;
  1759.         case TE_CNTR:
  1760.             x += (pb->pb_w - pxy[4])>>1;
  1761.         }
  1762.         y += (pb->pb_h - pxy[5])>>1;
  1763.     }
  1764.  
  1765.     v_gtext(x_handle,x,y,(char *) text->string);
  1766.  
  1767.     if (effect)
  1768.         vst_effects(x_handle,0);
  1769.  
  1770.     return(FALSE);
  1771. }
  1772.  
  1773. int cdecl draw_menu(PARMBLK *pb)
  1774. {
  1775.     reg int pxy[4];
  1776.     
  1777.     v_set_mode(MD_REPLACE);
  1778.     v_set_fill(BLACK,2,4);
  1779.     
  1780.     pxy[0] = pb->pb_x;
  1781.     pxy[1] = pb->pb_y + (pb->pb_h>>1) - 1;
  1782.     pxy[2] = pxy[0] + pb->pb_w - 1;
  1783.     pxy[3] = pxy[1] + 1;
  1784.     vr_recfl(x_handle,pxy);
  1785.     
  1786.     return(FALSE);
  1787. }
  1788.  
  1789. void init_xformdo(int ed_obj,EVENT *event,boolean top)
  1790. {
  1791.     reg OBJECT *tree = dinfo->di_tree,*obj = tree;
  1792.     reg int index = 0,eobjc,iobjc;
  1793.     reg unsigned short flg,type;
  1794.  
  1795.     dinfo->di_ed_obj = dinfo->di_default = dinfo->di_help = dinfo->di_undo = eobjc = iobjc = FAIL;
  1796.     dinfo->di_ed_objptr = NULL;
  1797.     w_init = FALSE;
  1798.  
  1799.     if (dinfo->di_flag>CLOSED)
  1800.     {
  1801.         do
  1802.         {
  1803.             obj++;index++;
  1804.             if ((flg = obj->ob_flags) & DEFAULT)
  1805.             {
  1806.                 if (!is_hidden(tree,index,TRUE))
  1807.                 {
  1808.                 #ifdef DEBUG
  1809.                     if (dinfo->di_default>=0)
  1810.                         form_alert(1,DEFAULT_ERR);
  1811.                     else
  1812.                 #endif
  1813.                         dinfo->di_default = index;
  1814.                 }
  1815.             }
  1816.             else if (flg & EDITABLE)
  1817.             {
  1818.                 if (!is_hidden(tree,index,FALSE))
  1819.                 {
  1820.                     if (flg & INDDEFAULT)
  1821.                     {
  1822.                     #ifdef DEBUG
  1823.                         if (iobjc>=0)
  1824.                             form_alert(1,INDDEFAULT_ERR);
  1825.                         else
  1826.                     #endif
  1827.                             iobjc = index;
  1828.                     }
  1829.     
  1830.                     if ((eobjc<0) || (index==ed_obj))
  1831.                         eobjc = index;
  1832.                 }
  1833.             }
  1834.             else
  1835.             {
  1836.                 type = obj->ob_type & (~G_MODAL);
  1837.             #ifdef DEBUG
  1838.                 if (type==G_CHK || type==G_RB)
  1839.                 {
  1840.                     if (!is_hidden(tree,index,TRUE))
  1841.                     {
  1842.                         reg char *err=NULL,msg[40];
  1843.     
  1844.                         switch (_get_hotkey(tree,index))
  1845.                         {
  1846.                         case FAIL:
  1847.                             err = (type==G_RB) ? RBHOTKEY_ERR_A : CHKHOTKEY_ERR_A;
  1848.                             break;
  1849.                         case FALSE:
  1850.                             err = (type==G_RB) ? RBHOTKEY_ERR_B : CHKHOTKEY_ERR_B;
  1851.                         }
  1852.     
  1853.                         if (err)
  1854.                         {
  1855.                             sprintf(msg,err,index);
  1856.                             form_alert(1,msg);
  1857.                         }
  1858.                     }
  1859.                 }
  1860.                 else
  1861.                 {
  1862.                     type >>= 8;
  1863.     
  1864.                     if (type==HELP_BTN && !is_hidden(tree,index,TRUE))
  1865.                     {
  1866.                         if (dinfo->di_help>=0)
  1867.                             form_alert(1,HELP_ERR);
  1868.                         else
  1869.                             dinfo->di_help = index;
  1870.                     }
  1871.                     else if (type==UNDO_BTN && !is_hidden(tree,index,TRUE))
  1872.                     {
  1873.                         if (dinfo->di_undo>=0)
  1874.                             form_alert(1,UNDO_ERR);
  1875.                         else
  1876.                             dinfo->di_undo = index;
  1877.                     }
  1878.                 }
  1879.             #else
  1880.                 type >>= 8;
  1881.     
  1882.                 if (type==HELP_BTN && !is_hidden(tree,index,TRUE))
  1883.                     dinfo->di_help = index;
  1884.                 else if (type==UNDO_BTN && !is_hidden(tree,index,TRUE))
  1885.                     dinfo->di_undo = index;
  1886.             #endif
  1887.             }
  1888.         }
  1889.         while (!(flg & LASTOB));
  1890.  
  1891.         mouse_flag = 0;
  1892.         graf_mouse(ARROW,NULL);
  1893.     
  1894.         if (!dinfo->di_iconified && eobjc>0 && top)
  1895.         {
  1896.             hist_index = 0;
  1897.             sel_edit(tree,eobjc,FAIL);
  1898.     
  1899.             _mouse_pos(&event->ev_mmox,&event->ev_mmoy);
  1900.             mouse_cursor(event);
  1901.     
  1902.             if (iobjc>0)
  1903.                 test_inddefault(tree,&dinfo->di_tree[iobjc]);
  1904.         }
  1905.     }
  1906.  
  1907.     {
  1908.         reg int *ev = (int *) event;
  1909.  
  1910.         *ev = MU_KEYBD|MU_BUTTON|MU_MESAG;
  1911.         if (dinfo->di_ed_obj>0 && !dinfo->di_iconified && win_topped(dinfo))
  1912.             *ev |= MU_M1;
  1913.         ev++;
  1914.         *ev++ = 2;
  1915.         *ev++ = 1;
  1916.         *ev++ = 1;
  1917.     }
  1918. }
  1919.  
  1920. void close_dials()
  1921. {
  1922.     while (_dia_len>0)
  1923.         close_dialog(_dia_list[_dia_len-1],FALSE);
  1924.     while (win_len>0)
  1925.         close_dialog(win_list[win_len-1],FALSE);
  1926. }
  1927.  
  1928. boolean find_window(reg int hdl,DIAINFO **info)
  1929. {
  1930.     reg int index;
  1931.  
  1932.     for (index=0;index<win_len;index++)
  1933.     {
  1934.         if (win_list[index]->di_handle == hdl)
  1935.         {
  1936.             *info = win_list[index];
  1937.             return(TRUE);
  1938.         }
  1939.     }
  1940.     return(FALSE);
  1941. }
  1942.  
  1943. void top_window(EVENT *event,DIAINFO *info)
  1944. {
  1945.     int index;
  1946.  
  1947.     if (info->di_ed_objptr)
  1948.         index=info->di_ed_index;
  1949.     else
  1950.         index=FAIL;
  1951.  
  1952.     dinfo = info;
  1953.     win_top = TRUE;
  1954.     dial = FALSE;
  1955.     wind_set(info->di_handle,WF_TOP);
  1956.     init_xformdo(info->di_ed_obj,event,TRUE);
  1957.  
  1958.     if (info->di_ed_obj>0)
  1959.     {
  1960.         if (index>=0)
  1961.             edit_pos(index,TRUE);
  1962.         else
  1963.             edit_on();
  1964.     }
  1965. }
  1966.  
  1967. int do_func(int msg,EVENT *event)
  1968. {
  1969.     if (xf_msg && (x_events & msg))
  1970.     {
  1971.         int old = event->ev_mwich,hdl,dummy;
  1972.  
  1973.         if (!_dia_len)
  1974.             wind_get(0,WF_TOP,&hdl,&dummy,&dummy,&dummy);
  1975.  
  1976.         call_func = TRUE;
  1977.  
  1978.         event->ev_mwich = msg;
  1979.         xf_msg(event);
  1980.         event->ev_mwich = old;
  1981.  
  1982.         call_func = FALSE;
  1983.  
  1984.         if (!_dia_len && !win_len)
  1985.         {
  1986.             exit_obj = W_ABANDON;
  1987.             x_abort = TRUE;
  1988.         }
  1989.         else if (w_init)
  1990.         {
  1991.             re_init(event);
  1992.             w_init = FALSE;
  1993.         }
  1994.         else if (!_dia_len)
  1995.         {
  1996.             wind_get(0,WF_TOP,&old,&dummy,&dummy,&dummy);
  1997.             if (old!=hdl)
  1998.                 re_init(event);
  1999.         }
  2000.     }
  2001.  
  2002.     return (x_abort);
  2003. }
  2004.  
  2005. void re_init(EVENT *event)
  2006. {
  2007.     reg int init = w_init;
  2008.  
  2009.     if (_dia_len>0)
  2010.     {
  2011.         dial = TRUE;
  2012.         win_top = modal = FALSE;
  2013.         dinfo = _dia_list[_dia_len-1];
  2014.  
  2015.         init_xformdo(dinfo->di_ed_obj,event,TRUE);
  2016.         if (dinfo->di_ed_obj>0)
  2017.         {
  2018.             if (init==TRUE)
  2019.                 edit_on();
  2020.             else
  2021.                 cursor(TRUE);
  2022.         }
  2023.     }
  2024.     else if (win_len>0)
  2025.     {
  2026.         DIAINFO *winfo;
  2027.         int     hdl,dummy;
  2028.  
  2029.         if (win_top)
  2030.             cursor(FALSE);
  2031.  
  2032.         dial = FALSE;
  2033.         wind_get(0,WF_TOP,&hdl,&dummy,&dummy,&dummy);
  2034.         if ((win_top=find_window(hdl,&winfo))>0)
  2035.         {
  2036.             if (win_list[win_len-1]->di_flag==WIN_MODAL)
  2037.                 winfo = win_list[win_len-1];
  2038.  
  2039.             if (!winfo->di_iconified)
  2040.             {
  2041.                 top_window(event,winfo);
  2042.                 if (winfo->di_ed_obj>0 && init==FALSE)
  2043.                     cursor(TRUE);
  2044.                 modal = (winfo->di_flag==WIN_MODAL);
  2045.             }
  2046.             else
  2047.             {
  2048.                 win_top = FALSE;
  2049.                 wind_set(winfo->di_handle,WF_TOP);
  2050.                 init_xformdo(winfo->di_ed_obj,event,FALSE);
  2051.             }
  2052.         }
  2053.         else
  2054.         {
  2055.             dinfo = win_list[win_len-1];
  2056.             init_xformdo(dinfo->di_ed_obj,event,FALSE);
  2057.         }
  2058.     }
  2059.  
  2060.     x_events = (xf_init) ? xf_init(event) : 0;
  2061. }
  2062.  
  2063. int X_Form_Do(DIAINFO **back,int edit,int (*init)(EVENT *),void (*call_func)(EVENT *))
  2064. {
  2065.     DIAINFO *info;
  2066.     EVENT    event;
  2067.     boolean back_click;
  2068.     long    last_time = clock();
  2069.     int        *mbuf = event.ev_mmgpbuf;
  2070.  
  2071.     mouse_flag = dial = back_click = x_abort = modal = FALSE;
  2072.     xf_init = init; xf_msg = call_func;
  2073.  
  2074.     if (_dia_len>0)
  2075.     {
  2076.         dinfo = _dia_list[_dia_len-1];
  2077.         dial = TRUE;
  2078.         win_top = FALSE;
  2079.     }
  2080.     else
  2081.     {
  2082.         DIAINFO *winfo;
  2083.         int     hdl,dummy;
  2084.  
  2085.         wind_get(0,WF_TOP,&hdl,&dummy,&dummy,&dummy);
  2086.         if ((win_top = find_window(hdl,&winfo))>0)
  2087.             dinfo = winfo;
  2088.         else
  2089.             dinfo = win_list[win_len-1];
  2090.         if (dinfo->di_flag==WIN_MODAL)
  2091.             modal = TRUE;
  2092.     }
  2093.  
  2094.     if (edit>0)
  2095.     {
  2096.         init_xformdo(edit,&event,dial|win_top);
  2097.         if (dinfo->di_ed_obj>0)
  2098.             edit_on();
  2099.     }
  2100.     else
  2101.     {
  2102.         if (dinfo->di_ed_objptr)
  2103.         {
  2104.             int index = dinfo->di_ed_index;
  2105.             init_xformdo(dinfo->di_ed_obj,&event,dial|win_top);
  2106.             if (dinfo->di_ed_obj>0 && index>=0)
  2107.                 edit_pos(index,TRUE);
  2108.         }
  2109.         else
  2110.         {
  2111.             init_xformdo(0,&event,dial|win_top);
  2112.             if (dinfo->di_ed_obj>0)
  2113.                 edit_on();
  2114.         }
  2115.     }
  2116.  
  2117.     x_events = (init) ? init(&event) : 0;
  2118.  
  2119.     for(;;)
  2120.     {
  2121.         event.ev_mwich = Event_Multi(&event,last_time);
  2122.         if (event.ev_mwich & MU_MESAG)
  2123.         {
  2124.             DIAINFO  *winfo;
  2125.             reg int msg=mbuf[0];
  2126.             boolean  found,win;
  2127.  
  2128.             found = win = FALSE;
  2129.  
  2130.             switch (msg)
  2131.             {
  2132.             case AC_OPEN:
  2133.             case MN_SELECTED:
  2134.             case AP_DRAGDROP:
  2135.             case WM_ALLICONIFY:
  2136.                 break;
  2137.             case AC_CLOSE:
  2138.             case AP_TERM:
  2139.                 win = TRUE;
  2140.                 break;
  2141.             case WM_NEWTOP:
  2142.             case WM_TOPPED:
  2143.             case WM_ONTOP:
  2144.                 msg = WM_TOPPED;
  2145.                 win = TRUE;
  2146.             default:
  2147.                 if (msg<256)
  2148.                     found = find_window(mbuf[3],&winfo);
  2149.                 break;
  2150.             }
  2151.  
  2152.             if ((found && _dia_len==0) || win)
  2153.             {
  2154.                 switch(msg)
  2155.                 {
  2156.                 case WM_REDRAW:
  2157.                     redraw_dialog(winfo,(GRECT *) &mbuf[4]);
  2158.                     break;
  2159.                 case WM_ICONIFY:
  2160.                     winfo->di_iconified = TRUE;
  2161.                     if (winfo==dinfo)
  2162.                         re_init(&event);
  2163.                     wind_set(winfo->di_handle,WF_ICONIFY,mbuf[4],mbuf[5],mbuf[6],mbuf[7]);
  2164.                     break;
  2165.                 case WM_UNICONIFY:
  2166.                     winfo->di_iconified = FALSE;
  2167.                     wind_set(winfo->di_handle,WF_UNICONIFY,mbuf[4],mbuf[5],mbuf[6],mbuf[7]);
  2168.                     if (winfo==dinfo)
  2169.                         re_init(&event);
  2170.                     break;
  2171.                 case WM_BOTTOMED:
  2172.                     if (!modal && win_top)
  2173.                     {
  2174.                         cursor(FALSE);
  2175.                         wind_set(mbuf[3],WF_BOTTOM);
  2176.                         win_top = FALSE;
  2177.                     }
  2178.                     break;
  2179.                 case WM_UNTOPPED:
  2180.                     if (winfo==dinfo && win_top)
  2181.                     {
  2182.                         cursor(FALSE);
  2183.                         win_top = FALSE;
  2184.                     }
  2185.                     break;
  2186.                 case WM_TOPPED:
  2187.                     if (_bevent || !_back_win || (!found && (!(x_events & MU_BUTTON) || modal)) || (modal && winfo!=dinfo))
  2188.                     {
  2189.                         topped:
  2190.                         if (win_top)
  2191.                             cursor(FALSE);
  2192.  
  2193.                         if (found || modal)
  2194.                         {
  2195.                             if (modal)
  2196.                                 winfo = win_list[win_len-1];
  2197.                             top_window(&event,winfo);
  2198.                             x_events = (init) ? init(&event) : 0;
  2199.                         }
  2200.                         else
  2201.                             do_func(MU_MESAG,&event);
  2202.                     }
  2203.                     else if (!modal || winfo==dinfo || !found)
  2204.                     {
  2205.                         int x,y;
  2206.                         GRECT win;
  2207.  
  2208.                         _mouse_pos(&x,&y);
  2209.                         wind_get(mbuf[3],WF_WORKXYWH,&win.g_x,&win.g_y,&win.g_w,&win.g_h);
  2210.  
  2211.                         if (rc_inside(x,y,&win))
  2212.                         {
  2213.                             event.ev_mwich |= MU_BUTTON;
  2214.                             event.ev_mbreturn = 1;
  2215.                             event.ev_mmox = x;
  2216.                             event.ev_mmoy = y;
  2217.                             back_click = TRUE;
  2218.                         }
  2219.                         else
  2220.                             goto topped;
  2221.                     }
  2222.                     break;
  2223.                 case WM_CLOSED:
  2224.                     if (!modal)
  2225.                     {
  2226.                         dinfo = winfo;
  2227.                         exit_obj = W_CLOSED;
  2228.                         x_abort = TRUE;
  2229.                     }
  2230.                     break;
  2231.                 case AP_TERM:
  2232.                 case AC_CLOSE:
  2233.                     ac_close=(msg==AC_CLOSE);
  2234.                     close_dials();
  2235.                     do_func(MU_MESAG,&event);
  2236.                     ac_close=0;
  2237.                     break;
  2238.                 case WM_MOVED:
  2239.                     move_dialog(winfo,(GRECT *) &mbuf[4]);
  2240.                     _mouse_pos(&event.ev_mmox,&event.ev_mmoy);
  2241.                     mouse_cursor(&event);
  2242.                     break;
  2243.                 }
  2244.             }
  2245.             else if (!found)
  2246.                 do_func(MU_MESAG,&event);
  2247.         }
  2248.  
  2249.         if (!_dia_len && !win_len && !x_abort)
  2250.         {
  2251.             exit_obj = W_ABANDON;
  2252.             x_abort = TRUE;
  2253.         }
  2254.  
  2255.         if (x_abort)
  2256.             break;
  2257.  
  2258.         if (event.ev_mwich & MU_BUTTON)
  2259.         {
  2260.             int klick=FAIL;
  2261.  
  2262.             if (dial)
  2263.                 klick = klickobj(dinfo,&event,&exit_obj,TRUE);
  2264.             else
  2265.             {
  2266.                 DIAINFO *winfo;
  2267.                 int handle,dummy;
  2268.  
  2269.                 if (!back_click)
  2270.                 {
  2271.                     if (_bevent || (event.ev_mmobutton & 2))
  2272.                         handle = wind_find(event.ev_mmox,event.ev_mmoy);
  2273.                     else
  2274.                     {
  2275.                         wind_get(0,WF_TOP,&handle,&dummy,&dummy,&dummy);
  2276.                         back_click = FAIL;
  2277.                     }
  2278.                 }
  2279.                 else
  2280.                     handle = mbuf[3];
  2281.  
  2282.                 if (win_top && dinfo->di_handle==handle)
  2283.                 {
  2284.                     if (back_click<0 || win_topped(dinfo))
  2285.                         klick = klickobj(dinfo,&event,&exit_obj,TRUE);
  2286.                     else
  2287.                     {
  2288.                         winfo = dinfo;
  2289.                         goto back;
  2290.                     }
  2291.                 }
  2292.                 else if (!modal && find_window(handle,&winfo))
  2293.                 {
  2294.                     back:
  2295.                     if (back_click>0 && !_bevent && (_mouse_but() & 1))
  2296.                         appl_tplay(record,3,100);
  2297.  
  2298.                     if ((klick = klickobj(winfo,&event,&exit_obj,FALSE))==0)
  2299.                     {
  2300.                         x_abort = FAIL;
  2301.                         info = winfo;
  2302.                         break;
  2303.                     }
  2304.                 }
  2305.                 back_click = FALSE;
  2306.             }
  2307.  
  2308.             if (!klick || (klick<0 && !modal && !dial && do_func(MU_BUTTON,&event)))
  2309.                 break;
  2310.         }
  2311.  
  2312.         if (event.ev_mwich & MU_KEYBD)
  2313.         {
  2314.             key_taken = FALSE;
  2315.             if (win_top || dial)
  2316.             {
  2317.                 exit_obj = key_handler(dinfo->di_tree,event.ev_mmokstate,event.ev_mkreturn,&event);
  2318.                 if (exit_obj!=FAIL && exit_obj)
  2319.                     break;
  2320.             }
  2321.  
  2322.             if (!key_taken && (always_keys || (!modal && !dial && !menu_dropped(NULL))) && do_func(MU_KEYBD,&event))
  2323.                 break;
  2324.         }
  2325.  
  2326.         if (event.ev_mwich & MU_M1)
  2327.             if ((win_top || dial) && dinfo->di_ed_obj>0)
  2328.                 mouse_cursor(&event);
  2329.  
  2330.         if (event.ev_mwich & (MU_M2|MU_TIMER))
  2331.         {
  2332.             if (do_func(event.ev_mwich & (MU_M2|MU_TIMER),&event))
  2333.                 break;
  2334.             if (event.ev_mwich & MU_TIMER)
  2335.                 last_time = clock();
  2336.         }
  2337.     }
  2338.  
  2339.     if (dinfo->di_ed_obj>0)
  2340.     {
  2341.         insert_history(dinfo->di_ed_objptr->ob_spec.tedinfo->te_ptext);
  2342.         if (x_abort!=TRUE && win_topped(dinfo))
  2343.             edit_off();
  2344.     }
  2345.  
  2346.     if (back)
  2347.     {
  2348.         if (exit_obj!=W_ABANDON)
  2349.         {
  2350.             if (x_abort<0)
  2351.                 *back = info;
  2352.             else
  2353.                 *back = dinfo;
  2354.         }
  2355.         else
  2356.             *back = NULL;
  2357.     }
  2358.  
  2359.     return (exit_obj);
  2360. }
  2361.  
  2362. boolean win_topped(DIAINFO *info)
  2363. {
  2364.     int top,dummy;
  2365.  
  2366.     if (info->di_flag<WINDOW)
  2367.         return(TRUE);
  2368.  
  2369.     wind_get(0,WF_TOP,&top,&dummy,&dummy,&dummy);
  2370.     if (info->di_handle==top)
  2371.         return(TRUE);
  2372.     else
  2373.         return(FALSE);
  2374. }
  2375.  
  2376. void cursor(int on_off)
  2377. {
  2378.     if (dinfo->di_ed_obj>0)
  2379.     {
  2380.         GRECT area;
  2381.  
  2382.         objc_offset(dinfo->di_tree,dinfo->di_ed_obj,&area.g_x,&area.g_y);
  2383.         area.g_x -= 2;
  2384.         area.g_y -= 4;
  2385.         area.g_w = dinfo->di_ed_objptr->ob_width+4;
  2386.         area.g_h = dinfo->di_ed_objptr->ob_height+8;
  2387.         ob_draw_chg(dinfo,ROOT,&area,FAIL,FALSE);
  2388.         dinfo->di_cursor = 0;
  2389.  
  2390.         if (on_off)
  2391.             edit_on();
  2392.     }
  2393. }
  2394.  
  2395. void mouse_cursor(EVENT *ev)
  2396. {
  2397.     reg OBJECT *tree=dinfo->di_tree,*ob_ptr;
  2398.     reg int obj,x=ev->ev_mmox,y=ev->ev_mmoy;
  2399.  
  2400.     if ((obj=objc_find(tree,ROOT,MAX_DEPTH,x,y))>=0)
  2401.     {
  2402.         ob_ptr = &tree[obj];
  2403.  
  2404.         ev->ev_mm1flags = 1;
  2405.         if ((ob_ptr->ob_flags & EDITABLE) && !(ob_ptr->ob_state & DISABLED))
  2406.         {
  2407.             VRECT     edit;
  2408.             int      dummy;
  2409.  
  2410.             edit_rect(tree,obj,&edit,&dummy);
  2411.             if ((x>=edit.v_x1) && (y>=edit.v_y1) && (x<=edit.v_x2) && (y<=edit.v_y2))
  2412.             {
  2413.                 if (!mouse_flag)
  2414.                 {
  2415.                     graf_mouse(TEXT_CRSR,NULL);
  2416.                     mouse_flag = 1;
  2417.                 }
  2418.  
  2419.                 ev->ev_mm1x = edit.v_x1;
  2420.                 ev->ev_mm1y = edit.v_y1;
  2421.                 ev->ev_mm1width = (edit.v_x2 - edit.v_x1 + 1);
  2422.                 ev->ev_mm1height = (edit.v_y2 - edit.v_y1 + 1);
  2423.                 return;
  2424.             }
  2425.         }
  2426.  
  2427.         if (ob_ptr->ob_head<0)
  2428.         {
  2429.             objc_offset(tree,obj,&ev->ev_mm1x,&ev->ev_mm1y);
  2430.             ev->ev_mm1width = ob_ptr->ob_width;
  2431.             ev->ev_mm1height = ob_ptr->ob_height;
  2432.         }
  2433.         else
  2434.         {
  2435.             ev->ev_mm1x = x - 1;
  2436.             ev->ev_mm1y = y - 1;
  2437.             ev->ev_mm1width = 3;
  2438.             ev->ev_mm1height = 2;
  2439.         }
  2440.     }
  2441.     else
  2442.     {
  2443.         ev->ev_mm1flags = 0;
  2444.         *(GRECT *) &ev->ev_mm1x = *(GRECT *) &tree->ob_x;
  2445.     }
  2446.  
  2447.     if (mouse_flag)
  2448.     {
  2449.         graf_mouse(ARROW,NULL);
  2450.         mouse_flag = 0;
  2451.     }
  2452. }
  2453.  
  2454. int klickobj(DIAINFO *info,EVENT *event,int *obj,boolean top)
  2455. {
  2456.     OBJECT *tree = info->di_tree;
  2457.  
  2458.     if ((*obj = objc_find(tree,ROOT,MAX_DEPTH,event->ev_mmox,event->ev_mmoy))>=0)
  2459.     {
  2460.         int dummy,ind=FALSE;
  2461.  
  2462.         if ((dummy = is_rb_chk(tree,*obj))>=0)
  2463.         {
  2464.             if (event->ev_mbreturn!=2 && !(tree[*obj].ob_flags & EDITABLE) &&
  2465.                 !(tree[*obj].ob_state & DISABLED))
  2466.             {
  2467.                 *obj = dummy;
  2468.                 ind = TRUE;
  2469.             }
  2470.         }
  2471.         else if (info->di_fly && nonsel_fly && !(tree[*obj].ob_flags & (SELECTABLE|EDITABLE|EXIT|TOUCHEXIT)))
  2472.         {
  2473.             evnt_timer(20,0);
  2474.             if (_mouse_but() & 1)
  2475.             {
  2476.                 do_jump_fly(tree,FAIL,0);
  2477.                 return(TRUE);
  2478.             }
  2479.         }
  2480.  
  2481.         dummy = objekt_handler(info,*obj,event->ev_mbreturn,event->ev_mmox,event->ev_mmoy,ind,top);
  2482.  
  2483.         if (dummy)
  2484.         {
  2485.             if (dummy!=FAIL)
  2486.             {
  2487.                 *obj = dummy;
  2488.                 return(FALSE);
  2489.             }
  2490.             else if (!top)
  2491.             {
  2492.                 cursor(FALSE);
  2493.                 top_window(event,info);
  2494.                 x_events = (xf_init) ? xf_init(event) : 0;
  2495.             }
  2496.         }
  2497.  
  2498.         return(TRUE);
  2499.     }
  2500.     else if (info->di_fly)
  2501.     {
  2502.         do_jump_fly(tree,event->ev_mmox,event->ev_mmoy);
  2503.         mouse_cursor(event);
  2504.         _no_click();
  2505.         return(TRUE);
  2506.     }
  2507.     else
  2508.         return(FAIL);
  2509. }
  2510.  
  2511. int key_handler(OBJECT *tree,int state,int scan,EVENT *event)
  2512. {
  2513.     reg int sn=(int) (((unsigned) scan)>>8),obj,hot,shft;
  2514.  
  2515.     shft = (state & 3) ? TRUE : FALSE;
  2516.     hot = shft ? 6 : 4;
  2517.  
  2518.     if (!state)
  2519.     {
  2520.         obj = FAIL;
  2521.  
  2522.         switch (sn)
  2523.         {
  2524.         case SCANRET:
  2525.             if (return_default || dinfo->di_ed_obj<0)
  2526.             {
  2527.                 key_taken = TRUE;
  2528.                 if (dinfo->di_default>0)
  2529.                     obj = dinfo->di_default;
  2530.                 else
  2531.                     return (FAIL);
  2532.             }
  2533.             break;
  2534.         case SCANENTER:
  2535.             if (dinfo->di_ed_obj<0 && dinfo->di_default>0)
  2536.                 obj = dinfo->di_default;
  2537.             break;
  2538.         case SCANHELP:
  2539.             obj = dinfo->di_help;
  2540.             break;
  2541.         case SCANUNDO:
  2542.             obj = dinfo->di_undo;
  2543.         }
  2544.  
  2545.         if (obj>0)
  2546.         {
  2547.             key_taken = TRUE;
  2548.             return(objekt_handler(dinfo,obj,hot,FAIL,FAIL,FALSE,TRUE));
  2549.         }
  2550.     }
  2551.  
  2552.     if ((state & K_ALT) || (dinfo->di_ed_obj<0 && !(state & K_CTRL)))
  2553.     {
  2554.         if ((obj = _is_hotkey(tree,scan,state))>=0)
  2555.         {
  2556.             key_taken = TRUE;
  2557.             if (!(hot & 2) && is_editable(tree,obj,tree[obj].ob_flags))
  2558.             {
  2559.                 sel_edit(tree,obj,TRUE);
  2560.                 return(FAIL);
  2561.             }
  2562.             else if (!is_hidden(tree,obj,TRUE))
  2563.                 return(objekt_handler(dinfo,obj,hot,FAIL,FAIL,FALSE,TRUE));
  2564.             else
  2565.                 return(FAIL);
  2566.         }
  2567.     }
  2568.  
  2569.     if (dinfo->di_ed_obj>0)
  2570.     {
  2571.         key_taken = TRUE;
  2572.  
  2573.         if (!cursor_handler(tree,state,sn,event))
  2574.         {
  2575.             if (sn==SCANUNDO)
  2576.                 edit_string(undobuff);
  2577.             else if (state & K_CTRL)
  2578.             {
  2579.                 reg char *text = dinfo->di_ed_objptr->ob_spec.tedinfo->te_ptext;
  2580.                 reg char *c    = text+dinfo->di_ed_index;
  2581.  
  2582.                 switch(sn)
  2583.                 {
  2584.                 case CTRLLEFT:
  2585.                     {
  2586.                         while ((c>text) && (word_ascii(*(--c))));
  2587.                         while ((c>text) && (!word_ascii(*(--c))));
  2588.                         if (c>text)
  2589.                             edit_pos((int) (c - text + 1),FALSE);
  2590.                         else
  2591.                             edit_pos(0,FALSE);
  2592.                     }
  2593.                     break;
  2594.                 case CTRLRIGHT:
  2595.                     {
  2596.                         while (word_ascii(*c++));
  2597.                         if (*(--c) != '\0')
  2598.                         {
  2599.                             while (!word_ascii(*c++));
  2600.                             if (*(--c) != '\0')
  2601.                                 edit_pos((int) (c - text),FALSE);
  2602.                         }
  2603.                         else
  2604.                             edit_pos((int) (c - text),FALSE);
  2605.                     }
  2606.                     break;
  2607.                 case SCANUP:
  2608.                     {
  2609.                         int o_i = hist_index;
  2610.                         insert_history(text);
  2611.                         if (shft)
  2612.                         {
  2613.                             reg size_t n = strlen(text);
  2614.                             if (n)
  2615.                             {
  2616.                                 reg int i;
  2617.                                 for (i=(hist_index!=o_i) ? 1 : 0;i<20;i++)
  2618.                                     if (!strncmp(history[i],text,n))
  2619.                                     {
  2620.                                         edit_string(history[i]);
  2621.                                         hist_index = i;
  2622.                                         break;
  2623.                                     }
  2624.                             }
  2625.                         }
  2626.                         else
  2627.                         {
  2628.                             if ((hist_index<19) && (history[hist_index+1][0]))
  2629.                                 hist_index++;
  2630.                             edit_string(history[hist_index]);
  2631.                         }
  2632.                     }
  2633.                     break;
  2634.                 case SCANDOWN:
  2635.                     {
  2636.                         insert_history(text);
  2637.                         if (shft)
  2638.                         {
  2639.                             reg size_t n = strlen(text);
  2640.                             if (n)
  2641.                             {
  2642.                                 reg int i;
  2643.                                 for (i=19;i>=0;i--)
  2644.                                     if (!strncmp(history[i],text,n))
  2645.                                     {
  2646.                                         edit_string(history[i]);
  2647.                                         hist_index = i;
  2648.                                         break;
  2649.                                     }
  2650.                             }
  2651.                         }
  2652.                         else
  2653.                         {
  2654.                             if ((hist_index>0) && (history[hist_index-1][0]))
  2655.                                 hist_index--;
  2656.                             edit_string(history[hist_index]);
  2657.                         }
  2658.                     }
  2659.                     break;
  2660.                 default:
  2661.                     {
  2662.                         int ascii = scan_2_ascii(scan,state),flag;
  2663.  
  2664.                         switch (ascii)
  2665.                         {
  2666.                         case 'X':
  2667.                         case 'C':
  2668.                             if (shft)
  2669.                                 flag = clipbrd_save(O_WRONLY|O_APPEND|O_CREAT);
  2670.                             else
  2671.                             {
  2672.                                 scrp_clear(0);
  2673.                                 flag = clipbrd_save(O_WRONLY|O_CREAT);
  2674.                             }
  2675.  
  2676.                             if (flag && ascii=='X')
  2677.                             {
  2678.                                 edit_off();
  2679.                                 *dinfo->di_ed_objptr->ob_spec.tedinfo->te_ptext = '\0';
  2680.                                 ob_draw_chg(dinfo,dinfo->di_ed_obj,NULL,FAIL,TRUE);
  2681.                                 edit_on();
  2682.                             }
  2683.                             break;
  2684.                         case 'V':
  2685.                             clipbrd_load((shft) ? TRUE : FALSE);
  2686.                             break;
  2687.                         default:
  2688.                             key_taken = FALSE;
  2689.                             break;
  2690.                         }
  2691.                     }
  2692.                     break;
  2693.                 }
  2694.             }
  2695.             else
  2696.             {
  2697.                 char string[128],*text=dinfo->di_ed_objptr->ob_spec.tedinfo->te_ptext;
  2698.  
  2699.                 strcpy(string,text);
  2700.                 edit_objc(tree,dinfo->di_ed_obj,scan,&dinfo->di_ed_index,ED_CHAR);
  2701.                 key_taken = strcmp(string,text);
  2702.             }
  2703.         }
  2704.  
  2705.         if (key_taken)
  2706.         {
  2707.             if ((dinfo->di_ed_objptr->ob_flags) & INDDEFAULT)
  2708.                 test_inddefault(tree,dinfo->di_ed_objptr);
  2709.  
  2710.             event->ev_mmgpbuf[0]=OBJC_EDITED;
  2711.             do_func(MU_MESAG,event);
  2712.         }
  2713.     }
  2714.     return(FAIL);
  2715. }
  2716.  
  2717. boolean clipbrd_save(int mode)
  2718. {
  2719.     char path[256],buf[128],*text=dinfo->di_ed_objptr->ob_spec.tedinfo->te_ptext;
  2720.     long len;
  2721.     int handle;
  2722.  
  2723.     scrp_read(path);
  2724.     if (*path)
  2725.     {
  2726.         strmfp(path,NULL,"SCRAP.TXT");
  2727.         if ((handle = open(path,mode))>0)
  2728.         {
  2729.             len = strlen(text);
  2730.             strcpy(buf,text);
  2731.             buf[len++] = '\r';
  2732.             buf[len++] = '\n';
  2733. #ifdef __MINT_LIB__
  2734.             write(handle,buf,(unsigned) len);
  2735. #else
  2736.             write(handle,buf,len);
  2737. #endif
  2738.             close(handle);
  2739.             return(TRUE);
  2740.         }
  2741.     }
  2742.     return(FALSE);
  2743. }
  2744.  
  2745. void clipbrd_load(boolean flag)
  2746. {
  2747.     char path[256],buf[128];
  2748.     int handle;
  2749.  
  2750.     scrp_read(path);
  2751.     if (path[0]!='\0')
  2752.     {
  2753.         strmfp(path,NULL,"SCRAP.TXT");
  2754.         if ((handle = open(path,O_RDONLY))>0)
  2755.         {
  2756.             if (read(handle,buf,127)>0);
  2757.             {
  2758.                 reg char *line;
  2759.                 
  2760.                 buf[127] = '\0';
  2761.                 if ((line = strchr(buf,'\r'))!=NULL || (line = strchr(buf,'\n'))!=NULL)
  2762.                     *line = '\0';
  2763.  
  2764.                 if (flag)
  2765.                 {
  2766.                     char str[256];
  2767.  
  2768.                     strcpy(str,dinfo->di_ed_objptr->ob_spec.tedinfo->te_ptext);
  2769.                     strcat(str,buf);
  2770.                     strncpy(buf,str,127);
  2771.                 }
  2772.  
  2773.                 edit_string(buf);
  2774.             }
  2775.             close(handle);
  2776.         }
  2777.     }
  2778. }
  2779.  
  2780. void edit_string(char *str)
  2781. {
  2782.     TEDINFO *ted=dinfo->di_ed_objptr->ob_spec.tedinfo;
  2783.     reg char *masc = ted->te_ptmplt;
  2784.     reg int len = 0;
  2785.  
  2786.     while (*masc)
  2787.         if (*masc++=='_') len++;
  2788.  
  2789.     edit_off();
  2790.     strncpy(ted->te_ptext,str,(long) len);
  2791.     ob_draw_chg(dinfo,dinfo->di_ed_obj,NULL,FAIL,TRUE);
  2792.     edit_on();
  2793. }
  2794.  
  2795. boolean word_ascii(char c)
  2796. {
  2797.     if (c)
  2798.     {
  2799.         if (isalnum(c))
  2800.             return(TRUE);
  2801.         else
  2802.         {
  2803.             reg char *ch = umlaute;
  2804.  
  2805.             while (*ch)
  2806.                 if (*ch++==c)
  2807.                     return(TRUE);
  2808.         }
  2809.     }
  2810.     return(FALSE);
  2811. }
  2812.  
  2813. void test_inddefault(OBJECT *tree,OBJECT *ind)
  2814. {
  2815.     reg OBJECT *obj = &tree[dinfo->di_default];
  2816.     reg int state;
  2817.  
  2818.     state = obj->ob_state;
  2819.  
  2820.     if ((*(ind->ob_spec.tedinfo->te_ptext))=='\0')
  2821.         state |= DISABLED;
  2822.     else
  2823.         state &= ~DISABLED;
  2824.  
  2825.     if (state!=(obj->ob_state))
  2826.     {
  2827.         obj->ob_state = state;
  2828.         ob_draw_chg(dinfo,dinfo->di_default,NULL,FAIL,FALSE);
  2829.     }
  2830. }
  2831.  
  2832. void insert_history(reg char *str)
  2833. {
  2834.     reg int i;
  2835.  
  2836.     if (strlen(str)>0l)
  2837.     {
  2838.         for (i=19;--i>=0;)
  2839.             if (!strcmp(history[i],str))
  2840.                 return;
  2841.  
  2842.         for (i=19;i>=1;i--)
  2843.             strcpy(history[i],history[i-1]);
  2844.         strcpy(history[0],str);
  2845.         if ((hist_index < 19) && (history[hist_index+1][0]))
  2846.             hist_index++;
  2847.     }
  2848. }
  2849.  
  2850. int cursor_handler(OBJECT *tree,int state,int scan,EVENT *event)
  2851. {
  2852.     if (!(state & K_CTRL))
  2853.     {
  2854.         if (state & 3)
  2855.         {
  2856.             switch(scan)
  2857.             {
  2858.             case SCANDEL:
  2859.                 {
  2860.                     char *text = dinfo->di_ed_objptr->ob_spec.tedinfo->te_ptext;
  2861.                     edit_off();
  2862.                     text[dinfo->di_ed_index] = '\0';
  2863.                     ob_draw_chg(dinfo,dinfo->di_ed_obj,NULL,FAIL,TRUE);
  2864.                     edit_on();
  2865.                 }
  2866.                 break;
  2867.             case SCANRET:
  2868.             case SCANENTER:
  2869.             case SCANTAB:
  2870.                 prev_edit(tree);
  2871.                 break;
  2872.             case SCANUP:
  2873.                 first_edit(tree);
  2874.                 break;
  2875.             case SCANHOME:
  2876.             case SCANDOWN:
  2877.                 last_edit(tree);
  2878.                 break;
  2879.             case SCANLEFT:
  2880.                 edit_pos(0,FALSE);
  2881.                 break;
  2882.             case SCANRIGHT:
  2883.                 edit_off();
  2884.                 edit_on();
  2885.                 break;
  2886.             case SCANINS:
  2887.                 _asc=TRUE;
  2888.                 _event=event;
  2889.                 ascii_box(dinfo->di_title,xf_init,xf_msg);
  2890.                 _asc=FALSE;
  2891.                 break;
  2892.             default:
  2893.                 return(FALSE);
  2894.             }
  2895.         }
  2896.         else
  2897.         {
  2898.             switch(scan)
  2899.             {
  2900.             case SCANHOME:
  2901.                 {
  2902.                     first_edit(tree);
  2903.                     edit_pos(0,FALSE);
  2904.                 }
  2905.                 break;
  2906.             case SCANUP:
  2907.                 prev_edit(tree);
  2908.                 break;
  2909.             case SCANDOWN:
  2910.             case SCANTAB:
  2911.             case SCANENTER:
  2912.             case SCANRET:
  2913.                 next_edit(tree);
  2914.                 break;
  2915.             case SCANINS:
  2916.                 edit_objc(tree,dinfo->di_ed_obj,' ',&dinfo->di_ed_index,ED_CHAR);
  2917.                 break;
  2918.             default:
  2919.                 return(FALSE);
  2920.             }
  2921.         }
  2922.         return(FAIL);
  2923.     }
  2924.     else
  2925.         return(FALSE);
  2926. }
  2927.  
  2928. char ascii_box(char *title,int (*init)(EVENT *),void (*call_func)(EVENT *))
  2929. {
  2930.     int exit;
  2931.  
  2932.     if (_asc)
  2933.         edit_off();
  2934.     exit = xdialog(ascii_tree,title,TRUE,FALSE,AUTO_DIAL|MODAL,init,call_func);
  2935.  
  2936.     if (exit>0)
  2937.     {
  2938.         if (exit!=CANCEL)
  2939.         {
  2940.             int x,ox,d,ascii;
  2941.  
  2942.             _mouse_pos(&x,&d);
  2943.             objc_offset(ascii_tree,exit,&ox,&d);
  2944.             _no_click();
  2945.  
  2946.             ascii = (exit - ASC0)<<5;
  2947.             if ((d = x-ox)>=0)
  2948.                 ascii += d/gr_cw;
  2949.  
  2950.             if (_asc)
  2951.             {
  2952.                 if (dinfo->di_flag>=WINDOW)
  2953.                     wind_set(WF_TOP,dinfo->di_handle);
  2954.                 re_init(_event);
  2955.                 edit_objc(dinfo->di_tree,dinfo->di_ed_obj,ascii,&dinfo->di_ed_index,ED_CHAR);
  2956.                 if ((dinfo->di_ed_objptr->ob_flags) & INDDEFAULT)
  2957.                     test_inddefault(dinfo->di_tree,dinfo->di_ed_objptr);
  2958.             }
  2959.             else
  2960.                 return(ascii);
  2961.         }
  2962.         else if (_asc)
  2963.             re_init(_event);
  2964.     }
  2965.  
  2966.     return(0);
  2967. }
  2968.  
  2969. void edit_off()
  2970. {
  2971.     int index = dinfo->di_ed_index;
  2972.  
  2973.     if (dinfo->di_cursor)
  2974.     {
  2975.         edit_objc(dinfo->di_tree,dinfo->di_ed_obj,0,&index,ED_END);
  2976.         dinfo->di_cursor = 0;
  2977.     }
  2978. }
  2979.  
  2980. void edit_on()
  2981. {
  2982.     if (dinfo->di_cursor==0)
  2983.     {
  2984.         edit_objc(dinfo->di_tree,dinfo->di_ed_obj,0,&dinfo->di_ed_index,ED_INIT);
  2985.         dinfo->di_cursor = 1;
  2986.     }
  2987. }
  2988.  
  2989. void sel_edit(OBJECT *tree,int obj,boolean off)
  2990. {
  2991.     if (off==TRUE)
  2992.         edit_off();
  2993.  
  2994.     if ((obj != dinfo->di_ed_obj) && (dinfo->di_ed_obj!=FAIL))
  2995.         insert_history(dinfo->di_ed_objptr->ob_spec.tedinfo->te_ptext);
  2996.  
  2997.     dinfo->di_ed_objptr = &tree[obj];
  2998.  
  2999.     if (obj != dinfo->di_ed_obj)
  3000.         strcpy(undobuff,dinfo->di_ed_objptr->ob_spec.tedinfo->te_ptext);
  3001.  
  3002.     dinfo->di_ed_obj = obj;
  3003.  
  3004.     if (off!=FAIL)
  3005.         edit_on();
  3006. }
  3007.  
  3008. boolean is_editable(OBJECT *tree,int obj,int flag)
  3009. {
  3010.     if ((flag & EDITABLE) && !is_hidden(tree,obj,FALSE))
  3011.         return(TRUE);
  3012.     else
  3013.         return(FALSE);
  3014. }
  3015.  
  3016. boolean is_hidden(OBJECT *tree,int index,boolean flag)
  3017. {
  3018.     reg OBJECT *obj = tree+index;
  3019.  
  3020.     if (obj->ob_flags & HIDETREE)
  3021.         return(TRUE);
  3022.     else if (flag || !(obj->ob_state & DISABLED))
  3023.     {
  3024.         reg int act;
  3025.  
  3026.         for (act=index;--act>=0;)
  3027.         {
  3028.             obj--;
  3029.             if (obj->ob_head<=index && obj->ob_tail>=index)
  3030.                 if (obj->ob_flags & HIDETREE)
  3031.                     return(TRUE);
  3032.                 else
  3033.                     index = act;
  3034.         }
  3035.  
  3036.         return(FALSE);
  3037.     }
  3038.     else
  3039.         return(TRUE);
  3040. }
  3041.  
  3042. void first_edit(OBJECT *tree)
  3043. {
  3044.     reg OBJECT *obj = tree;
  3045.     reg int index= 0;
  3046.  
  3047.     do
  3048.     {
  3049.         obj++;index++;
  3050.         if (is_editable(tree,index,obj->ob_flags))
  3051.         {
  3052.             sel_edit(tree,index,TRUE);
  3053.             break;
  3054.         }
  3055.     }
  3056.     while (!(obj->ob_flags & LASTOB));
  3057. }
  3058.  
  3059. void last_edit(OBJECT *tree)
  3060. {
  3061.     reg OBJECT *obj = tree;
  3062.     reg int index,last;
  3063.  
  3064.     index = last = 0;
  3065.     do
  3066.     {
  3067.         obj++;index++;
  3068.         if (is_editable(tree,index,obj->ob_flags))
  3069.             last = index;
  3070.     }
  3071.     while (!(obj->ob_flags & LASTOB));
  3072.  
  3073.     if (last)
  3074.         sel_edit(tree,last,TRUE);
  3075. }
  3076.  
  3077. void next_edit(OBJECT *tree)
  3078. {
  3079.     reg OBJECT *obj  = dinfo->di_ed_objptr;
  3080.     reg int index      = dinfo->di_ed_obj;
  3081.     reg boolean flag = FALSE;
  3082.  
  3083.     if (!(obj->ob_flags & LASTOB))
  3084.     {
  3085.         do
  3086.         {
  3087.             obj++;index++;
  3088.             if (is_editable(tree,index,obj->ob_flags))
  3089.             {
  3090.                 sel_edit(tree,index,TRUE);
  3091.                 flag = TRUE;
  3092.                 break;
  3093.             }
  3094.         }
  3095.         while (!(obj->ob_flags & LASTOB));
  3096.     }
  3097.     if (!flag)
  3098.         first_edit(tree);
  3099. }
  3100.  
  3101. void prev_edit(OBJECT *tree)
  3102. {
  3103.     reg OBJECT *obj = dinfo->di_ed_objptr;
  3104.     reg int index     = dinfo->di_ed_obj;
  3105.     reg int flag     = FALSE;
  3106.     do
  3107.     {
  3108.         obj--;index--;
  3109.         if (is_editable(tree,index,obj->ob_flags))
  3110.         {
  3111.             sel_edit(tree,index,TRUE);
  3112.             flag = TRUE;
  3113.             break;
  3114.         }
  3115.     } while (index>0);
  3116.     if (!flag)
  3117.         last_edit(tree);
  3118. }
  3119.  
  3120. void edit_pos(int index,boolean off)
  3121. {
  3122.     reg char c,*t=dinfo->di_ed_objptr->ob_spec.tedinfo->te_ptext;
  3123.     t += index;
  3124.  
  3125.     if (off==FALSE)
  3126.         edit_off();
  3127.     c = *t;
  3128.     *t = '\0';
  3129.     edit_on();
  3130.     *t = c;
  3131. }
  3132.  
  3133. int is_rb_chk(reg OBJECT *tree,reg int obj)
  3134. {
  3135.     reg int index = 0;
  3136.  
  3137.     for(;;)
  3138.     {
  3139.         if (tree->ob_next==obj)
  3140.             switch (tree->ob_type & (~G_MODAL))
  3141.             {
  3142.             case G_CHK:
  3143.             case G_RB:
  3144.                 return(index);
  3145.             }
  3146.  
  3147.         if (tree->ob_flags & LASTOB)
  3148.             break;
  3149.         else
  3150.         {
  3151.             tree++;
  3152.             index++;
  3153.         }
  3154.     }
  3155.     return(FAIL);
  3156. }
  3157.  
  3158. int _is_hotkey(OBJECT *tree,int key,int state)
  3159. {
  3160.     reg OBJECT *obj  = tree;
  3161.     reg int hot,index = 0,ascii = scan_2_ascii(key,state);
  3162.  
  3163.     do
  3164.     {
  3165.         obj++;index++;
  3166.         switch (obj->ob_type & (~G_MODAL))
  3167.         {
  3168.         case G_HOTKEY:
  3169.             if ((obj->ob_state>>8)==ascii)
  3170.                 return(ob_get_parent(tree,index));
  3171.             break;
  3172.         case G_CHK:
  3173.         case G_RB:
  3174.             if ((hot=_get_hotkey(tree,index))>0 && (tree[hot].ob_state>>8)==ascii)
  3175.                 return(index);
  3176.         }
  3177.     }
  3178.     while (!(obj->ob_flags & LASTOB));
  3179.  
  3180.     return(FAIL);
  3181. }
  3182.  
  3183. void edit_rect(OBJECT *tree,int obj,VRECT *edit,int *cw)
  3184. {
  3185.     reg OBJECT *obptr=&tree[obj];
  3186.     reg TEDINFO *ted=obptr->ob_spec.tedinfo;
  3187.     reg char *m;
  3188.     reg int x,w,we;
  3189.  
  3190.     objc_offset(tree,obj,&edit->v_x1,&edit->v_y1);
  3191.     if (ted->te_font==SMALL)
  3192.     {
  3193.         w = gr_sw;
  3194.         edit->v_y2 = gr_sh;
  3195.     }
  3196.     else
  3197.     {
  3198.         w = gr_cw;
  3199.         edit->v_y2 = gr_ch;
  3200.     }
  3201.  
  3202.     m  = ted->te_ptmplt;
  3203.     we = ((int) strlen(m))*w;
  3204.  
  3205.     switch(ted->te_just)
  3206.     {
  3207.     case TE_RIGHT:
  3208.         edit->v_x1 += obptr->ob_width-we-1;
  3209.         break;
  3210.     case TE_CNTR:
  3211.         edit->v_x1 += (obptr->ob_width-we)>>1;
  3212.         break;
  3213.     }
  3214.     edit->v_y1 += (obptr->ob_height - edit->v_y2)>>1;
  3215.     edit->v_y2 += edit->v_y1;
  3216.  
  3217.     while (*m!='\0' && *m++!='_')
  3218.         edit->v_x1 += w;
  3219.  
  3220.     m--;
  3221.     x = edit->v_x2 = edit->v_x1;
  3222.     while (*m!='\0')
  3223.     {
  3224.         x += w;
  3225.         if (*m++=='_')
  3226.             edit->v_x2 = x;
  3227.     }
  3228.     *cw = w;
  3229. }
  3230.  
  3231. int objekt_handler(DIAINFO *info,int obj,int hot,int x,int y,boolean ind,boolean top)
  3232. {
  3233.     reg OBJECT *tree = info->di_tree,*obptr = tree+obj;
  3234.     reg int flags = obptr->ob_flags;
  3235.     reg int state = obptr->ob_state;
  3236.  
  3237.     if (!(hot & 2) && (x!=FAIL) && (flags & EDITABLE))
  3238.     {
  3239.         if (top)
  3240.         {
  3241.             VRECT     edit;
  3242.             int      va;
  3243.  
  3244.             edit_rect(tree,obj,&edit,&va);
  3245.             if (!(obptr->ob_state & DISABLED) && (x>=edit.v_x1) && (y>=edit.v_y1) && (y<=edit.v_y2))
  3246.             {
  3247.                 reg TEDINFO *ted=obptr->ob_spec.tedinfo;
  3248.                 reg char *t=ted->te_ptext,*m=ted->te_ptmplt;
  3249.                 reg int pos,index;
  3250.  
  3251.                 while (*m!='\0' && *m++!='_');
  3252.                 pos = min((x-edit.v_x1+1)/va,(int) strlen(m)+1);
  3253.                 for (index=pos;--index>0;)
  3254.                     if (*m!='\0' && *m++!='_')
  3255.                         pos--;
  3256.                 pos = min(pos,(int) strlen(t));
  3257.                 
  3258.                 index = dinfo->di_ed_obj;
  3259.                 if (dinfo->di_ed_index!=pos || index!=obj)
  3260.                 {
  3261.                     t += pos;
  3262.                     va = *t;
  3263.                     *t = '\0';
  3264.                     sel_edit(tree,obj,TRUE);
  3265.                     *t = va;
  3266.                     if (index!=obj)
  3267.                         strcpy(undobuff,ted->te_ptext);
  3268.                 }
  3269.                 return(FALSE);
  3270.             }
  3271.         }
  3272.  
  3273.         {
  3274.             int dummy = is_rb_chk(tree,obj);
  3275.  
  3276.             if (dummy!=FAIL)
  3277.             {
  3278.                 obj = dummy;
  3279.                 obptr = tree+obj;
  3280.                 flags = obptr->ob_flags;
  3281.                 state = obptr->ob_state;
  3282.  
  3283.                 if (obptr->ob_state & DISABLED)
  3284.                     return(FAIL);
  3285.             }
  3286.  
  3287.             goto object_handle;
  3288.         }
  3289.     }
  3290.     else if (!(state & DISABLED))
  3291.     {
  3292.         object_handle:
  3293.         if ((obptr->ob_type & (~G_MODAL))==G_FLY || ((obptr->ob_type & (~G_MODAL))>>8)==USERFLY)
  3294.             do_jump_fly(tree,FAIL,0);
  3295.         else if (flags & (SELECTABLE|EXIT|TOUCHEXIT))
  3296.         {
  3297.             if (flags & SELECTABLE)
  3298.             {
  3299.                 if ((flags & RBUTTON) && (state & SELECTED))
  3300.                     _no_click();
  3301.                 else
  3302.                 {
  3303.                     state ^= SELECTED;
  3304.                     if ((hot & 4) || ind || (flags & (RBUTTON|TOUCHEXIT)))
  3305.                     {
  3306.                         obptr->ob_state = state;
  3307.                         ob_draw_chg(info,obj,NULL,FAIL,FALSE);
  3308.  
  3309.                         if (flags & RBUTTON)
  3310.                         {
  3311.                             reg int act = obj,lst,new;
  3312.  
  3313.                             for(;;)
  3314.                             {
  3315.                                 lst = act;
  3316.                                 new = obptr->ob_next;
  3317.  
  3318.                                 for(;;)
  3319.                                 {
  3320.                                     act = new;
  3321.                                     obptr  = tree+act;
  3322.  
  3323.                                     if (obptr->ob_tail==lst)
  3324.                                     {
  3325.                                         new = obptr->ob_head;
  3326.                                         lst = act;
  3327.                                     }
  3328.                                     else
  3329.                                     {
  3330.                                         if (act==obj)
  3331.                                             goto do_exit;
  3332.  
  3333.                                         if ((obptr->ob_state & SELECTED) && (obptr->ob_flags & RBUTTON))
  3334.                                         {
  3335.                                             obptr->ob_state &= ~SELECTED;
  3336.                                             ob_draw_chg(info,act,NULL,FAIL,FALSE);
  3337.                                             goto do_exit;
  3338.                                         }
  3339.                                         else
  3340.                                             break;
  3341.                                     }
  3342.                                 }
  3343.                             }
  3344.                         }
  3345.                         if ((ind || (flags & RBUTTON)) && !(flags & TOUCHEXIT))
  3346.                             _no_click();
  3347.                     }
  3348.                     else
  3349.                     {
  3350.                         reg OBJECT *ob = tree+obj;
  3351.                         EVENT event;
  3352.                         int x,y,events;
  3353.  
  3354.                         event.ev_mflags = MU_BUTTON|MU_M1;
  3355.                         event.ev_mbclicks = event.ev_bmask = 1;
  3356.                         event.ev_mbstate = 0;
  3357.  
  3358.                         objc_offset(tree,obj,&event.ev_mm1x,&event.ev_mm1y);
  3359.                         event.ev_mm1width = ob->ob_width;
  3360.                         event.ev_mm1height = ob->ob_height;
  3361.  
  3362.                         _mouse_pos(&x,&y);
  3363.                         if (rc_inside(x,y,(GRECT *) &event.ev_mm1x))
  3364.                         {
  3365.                             event.ev_mm1flags = 1;
  3366.                             ob->ob_state ^= SELECTED;
  3367.                             ob_draw_chg(info,obj,NULL,FAIL,FALSE);
  3368.                         }
  3369.                         else
  3370.                             event.ev_mm1flags = 0;
  3371.  
  3372.                         do
  3373.                         {
  3374.                             events = Event_Multi(&event,0);
  3375.                             if (events & MU_M1)
  3376.                             {
  3377.                                 event.ev_mm1flags = 1 - event.ev_mm1flags;
  3378.                                 ob->ob_state ^= SELECTED;
  3379.                                 ob_draw_chg(info,obj,NULL,FAIL,FALSE);
  3380.                             }
  3381.                         } while (!(events & MU_BUTTON));
  3382.  
  3383.                         if (!(ob->ob_state & SELECTED))
  3384.                             return(FALSE);
  3385.                     }
  3386.                 }
  3387.             }
  3388.             else if (flags & EXIT)
  3389.                 _no_click();
  3390.  
  3391.             do_exit:
  3392.             if (flags & (EXIT|TOUCHEXIT))
  3393.             {
  3394.                 if (hot & 2)
  3395.                     return(obj|0x8000);
  3396.                 else
  3397.                     return(obj);
  3398.             }
  3399.             else
  3400.                 return(FALSE);
  3401.         }
  3402.     }
  3403.     return(FAIL);
  3404. }
  3405.  
  3406. void edit_objc(OBJECT *tree,int obj,int scan,int *index,int mode)
  3407. {
  3408.     wind_update(BEG_UPDATE);
  3409.     objc_edit(tree,obj,scan,index,mode);
  3410.     wind_update(END_UPDATE);
  3411. }
  3412.  
  3413. void do_jump_fly(OBJECT *tree,int x,int y)
  3414. {
  3415.     MFDB dst;
  3416.     long mem;
  3417.  
  3418.     _beg_ctrl();
  3419.     dst.fd_addr = NULL;
  3420.  
  3421.     if ((long) Malloc(-1l)>(dinfo->di_length + 4096l))
  3422.         if ((mem = (long) Malloc(dinfo->di_length + 256l))>0l)
  3423.         {
  3424.             dst = dinfo->di_mfdb;
  3425.             dst.fd_addr = (int *) ((mem & 0xfffffffel) + 2);
  3426.             _bitblt(tree,&dst,TRUE);
  3427.         }
  3428.  
  3429.     _bitblt(tree,&dinfo->di_mfdb,FALSE);
  3430.  
  3431.     if (x<0)
  3432.     {
  3433.         graf_mouse(FLAT_HAND,NULL);
  3434.         graf_dragbox(tree->ob_width + 6,tree->ob_height + 6,
  3435.                      tree->ob_x - 3,tree->ob_y - 3,desk.g_x + 1,desk.g_y + 1,desk.g_w - 2,desk.g_h - 2,&tree->ob_x,&tree->ob_y);
  3436.         graf_mouse(ARROW,NULL);
  3437.         tree->ob_x += 3;tree->ob_y += 3;
  3438.     }
  3439.     else
  3440.     {
  3441.         int ox = tree->ob_x,oy = tree->ob_y;
  3442.         tree->ob_x = x - (tree->ob_width>>1);
  3443.         tree->ob_y = y - (tree->ob_height>>1);
  3444.         graf_movebox(tree->ob_width,tree->ob_height,ox,oy,tree->ob_x,tree->ob_y);
  3445.     }
  3446.  
  3447.     dial_pos(tree,4,3);
  3448.     _bitblt(tree,&dinfo->di_mfdb,TRUE);
  3449.  
  3450.     if (dst.fd_addr)
  3451.     {
  3452.         _bitblt(tree,&dst,FALSE);
  3453.         Mfree((void *) mem);
  3454.     }
  3455.     else
  3456.     {
  3457.         if (dinfo->di_ed_obj>0)
  3458.             edit_off();
  3459.  
  3460.         objc_draw(tree,ROOT,MAX_DEPTH,desk.g_x,desk.g_y,desk.g_w,desk.g_h);
  3461.  
  3462.         if (dinfo->di_ed_obj>0)
  3463.             edit_on();
  3464.     }
  3465.     _end_ctrl();
  3466. }
  3467.  
  3468. boolean open_rsc(char *rscname,char *m_entry)
  3469. {
  3470.     if (init_gem(m_entry)==TRUE)
  3471.     {
  3472.         if (rsrc_load(rscname))
  3473.         {
  3474.             reg OBJECT *obj;
  3475.             reg int index;
  3476.             OBJECT *tree=NULL;
  3477.             RSHDR *rsc=*((RSHDR **) &GLOBAL[7]);
  3478.  
  3479.             index = rsc->rsh_ntree;
  3480.             while (--index>=0 && rsrc_gaddr(R_TREE,index,&tree) && tree!=NULL)
  3481.             {
  3482.                 for (obj=tree;;)
  3483.                 {
  3484.                     if (obj->ob_x==0 && obj->ob_width>max_w)
  3485.                         obj->ob_width = max_w;
  3486.                     if (obj->ob_flags & LASTOB)
  3487.                         break;
  3488.                     else
  3489.                         obj++;
  3490.                 }
  3491.  
  3492.                 tree = NULL;
  3493.             }
  3494.             return(TRUE);
  3495.         }
  3496.         else
  3497.         {
  3498.             exit_gem();
  3499.             return(FAIL);
  3500.         }
  3501.     }
  3502.     else
  3503.         return(FALSE);
  3504. }
  3505.  
  3506. void close_rsc()
  3507. {
  3508.     rsrc_free();
  3509.     exit_gem();
  3510. }
  3511.  
  3512. boolean open_work(int *handle,int *work_out)
  3513. {
  3514.     reg int i,work_in[11];
  3515.  
  3516.     *handle = grhandle;
  3517.     for (i = 0; i <= 9; work_in[i++] = 1);work_in[i] = 2;
  3518.     v_opnvwk(work_in, handle, work_out);
  3519.  
  3520.     return((*handle>0) ? TRUE : FALSE);
  3521. }
  3522.  
  3523. void close_work(int handle)
  3524. {
  3525.     v_clsvwk(handle);
  3526. }
  3527.  
  3528. int xdialog(OBJECT *tree,char *name,boolean center,boolean shrgrw,int mode,int (*init)(EVENT *),void (*call_func)(EVENT *))
  3529. {
  3530.     DIAINFO info,*old=dinfo;
  3531.     int exit;
  3532.  
  3533.     open_dialog(tree,&info,name,center,shrgrw,mode);
  3534.     exit = X_Form_Do(0l, 0, init, call_func);
  3535.     if ((exit != W_ABANDON) && (exit != W_CLOSED))
  3536.     {
  3537.         exit &= 0x7fff;
  3538.         tree[exit].ob_state &= ~SELECTED;
  3539.     }
  3540.     close_dialog(&info,shrgrw);
  3541.     dinfo = old;
  3542.  
  3543.     return(exit);
  3544. }
  3545.  
  3546. void menu_enable(OBJECT *tree,boolean enable,boolean show)
  3547. {
  3548.     if (_app)
  3549.     {
  3550.         reg OBJECT *obj = tree;
  3551.         reg int index = 0,title = 0,string = 1;
  3552.  
  3553.         for (;;)
  3554.         {
  3555.             switch (obj->ob_type)
  3556.             {
  3557.             case G_TITLE:
  3558.                 if (title)
  3559.                     menu_ienable(tree,index,enable);
  3560.                 else
  3561.                     title = 1;
  3562.                 break;
  3563.             case G_STRING:
  3564.                 if (string)
  3565.                 {
  3566.                     menu_ienable(tree,index,enable);
  3567.                     string = 0;
  3568.                 }
  3569.             }
  3570.             if (obj->ob_flags & LASTOB)
  3571.                 break;
  3572.             else
  3573.             {
  3574.                 obj++;
  3575.                 index++;
  3576.             }
  3577.         }
  3578.  
  3579.         if (show)
  3580.             menu_bar(tree,1);
  3581.     }
  3582. }
  3583.  
  3584. boolean menu_dropped(OBJECT *m_tree)
  3585. {
  3586.     reg OBJECT *obj = (m_tree) ? m_tree : menu;
  3587.  
  3588.     if (obj)
  3589.         do
  3590.         {
  3591.             obj++;
  3592.             if (obj->ob_state & SELECTED)
  3593.                 return(TRUE);
  3594.         } while (!(obj->ob_flags & LASTOB));
  3595.     return(FALSE);
  3596. }
  3597.