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