home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic 4 Unleashed / Visual_Basic_4_Unleashed_SAMS_Publishing_1995.iso / repease / rep1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-02  |  65.1 KB  |  1,795 lines

  1. /*==============================================================================
  2.    REP1.C
  3.    Report Ease - Text Editing functions.
  4.  
  5.    ReportEase Plus
  6.    Sub Systems, Inc.
  7.    ReportEase Plus, Copyright (c) 1993, Sub Systems, Inc. All Rights Reserved.
  8.    159 Main Street, #8C, Stoneham,  MA 02180 
  9.    (617) 438-8901.
  10.  
  11.    Software License Agreement  (1993)              
  12.    ----------------------------------
  13.    This license agreement allows the purchaser the right to modify the 
  14.    source code to incorporate in their application.
  15.    The target application must not be distributed as a standalone report writer
  16.    or a mail merge product.
  17.    Sub Systems, Inc. reserves the right to prosecute anybody found to be 
  18.    making illegal copies of the executable software or compiling the source
  19.    code for the purpose of selling there after.
  20.  
  21. ===============================================================================*/
  22.  
  23. #include "windows.h"
  24.  
  25. #if defined (_WIN32)
  26.    #if !defined(WIN32)
  27.      #define WIN32
  28.    #endif
  29. #endif
  30. #if !defined(WIN32) 
  31.   #include "print.h"
  32. #endif
  33.  
  34. #include "stdio.h"
  35. #include "stdlib.h"
  36. #include "ctype.h"
  37. #include "dos.h"
  38. #include "fcntl.h"
  39. #include "io.h"
  40. #include "signal.h"
  41. #include "string.h"
  42. #include "malloc.h"
  43. #include "memory.h"
  44. #include "sys\types.h"
  45. #include "sys\stat.h"
  46. #include "setjmp.h"
  47.  
  48. #include "rep.h"
  49.  
  50. #define  PREFIX extern
  51. #include "rep1.h"
  52.  
  53. /******************************************************************************
  54.    InsertLabelPartI()
  55.    This routine initiates label creation.  It defines a cursor rectangle
  56.    for the new label.  When the user presses a mouse button, the 
  57.    InsertLabelPartII function is used to create at the label the current
  58.    cursor postion.
  59. *******************************************************************************/
  60. InsertLabelPartI()
  61. {
  62.    int LabelHeight,LabelWidth;
  63.    
  64.    if (CurCmd!=-1) return FALSE; // previous command not completed yet
  65.    
  66.    if (TotalItems>=MAX_ITEMS) {  // check for item table space
  67.       MessageBox(hFrWnd,"Item Table Full!",NULL,MB_OK);
  68.       return TRUE;
  69.    }
  70.  
  71.    // deselect currently selected item
  72.    if (SelItem>=0) DeselectItem();// deselect the current item
  73.  
  74.    // get label height and width
  75.    LabelHeight=CharHeight;
  76.    LabelWidth=GetLabelLen("Label",DEFAULT_CFMT)+2*DESC_MARGIN;
  77.  
  78.    // define the cursor rectangle
  79.    CursRect.left=FrWinOrgX+(FrWinWidth-LabelWidth)/2;
  80.    CursRect.right=CursRect.left+LabelWidth;
  81.    if (CursRect.right>FrWidth) {
  82.       CursRect.right=FrWidth;
  83.       CursRect.left=CursRect.right-LabelWidth;
  84.    }
  85.    if (CursRect.left<FrWinOrgX) CursRect.left=FrWinOrgX;
  86.    if (CursRect.left>=CursRect.right) return FALSE;
  87.  
  88.    CursRect.top=FrWinOrgY+(FrWinHeight-LabelHeight)/2;
  89.    CursRect.bottom=CursRect.top+LabelHeight;
  90.    if (CursRect.bottom>FrHeight) {
  91.       CursRect.bottom=FrHeight;
  92.       CursRect.top=CursRect.bottom-LabelHeight;
  93.    }
  94.    if (CursRect.top<FrWinOrgY) CursRect.top=FrWinOrgY;
  95.    if (CursRect.top>=CursRect.bottom) return FALSE;
  96.  
  97.    // Draw the focus rectangle
  98.    FrDrawFocusRect(hFrDC,&CursRect);
  99.    FrSetCursor(CursRect.left+(CursRect.right-CursRect.left)/2,CursRect.top+(CursRect.bottom-CursRect.top)/2);
  100.    
  101.    // set the flags
  102.    CurCmd=ID_INSERT_LABEL;            // current unfinished command
  103.    IgnoreMouseMove=FALSE;             // monitor mouse movements now
  104.    SelItem=-1;                        // no item selected yet
  105.  
  106.    return TRUE;
  107. }
  108.  
  109. /******************************************************************************
  110.    InsertLabelPartII()
  111.    This routine finishes the label creation process started by the
  112.    InsertLabelPartI function.  This function is called after the user
  113.    positions the cursor rectangle for the new label.
  114. *******************************************************************************/
  115. InsertLabelPartII()
  116. {
  117.     int CurItem,CurSec;
  118.     struct StrItem NewItem;
  119.  
  120.     FrEraseFocusRect(hFrDC,&CursRect);// erase the focus rectangle
  121.     CurSec=FrAdjustCursorRect();      // adjust the cursor rectangle position
  122.     CurItem=FrFindItemSlot(CurSec);   // slot where the item will be inserted
  123.  
  124.     // initialize the NewItem
  125.     InitItem(&NewItem);            // initialize
  126.     NewItem.type=LABEL;            // screen item type: LABEL,FIELD,SECTION,LINE
  127.     NewItem.x=CursRect.left;       // X position of the top/left corner of the object
  128.     NewItem.y=CursRect.top;        // Y position of the top/left coner of the object
  129.     NewItem.width=CursRect.right-CursRect.left; // width of the object 
  130.     NewItem.height=CursRect.bottom-CursRect.top;// height of the object
  131.     NewItem.flags=OFLAG_HCENTER|OFLAG_VCENTER;  // Attributes, see OFLAG_ constants 
  132.     NewItem.section=CurSec;        // Current section
  133.     lstrcpy(NewItem.label,"Label");// label text when type is LABEL
  134.  
  135.     // insert the new item
  136.     MoveItemArray(CurItem,1,'B');  // scroll down the array
  137.     HugeMove(&NewItem,&(item[CurItem]),sizeof(struct StrItem));
  138.  
  139.     // reset the flags
  140.     CurCmd=-1;                    // currnet command completed
  141.     IgnoreMouseMove=TRUE;
  142.     SetCursor(hArrowCursor);      // set the regular cursor
  143.     SelItem=CurItem;
  144.     PaintFlag=PAINT_WIN;          // to reset the option ribbon highlighting
  145.     FrPaint();                    // repaint the screen
  146.  
  147.     FrModified=TRUE;
  148.  
  149.     return TRUE;
  150. }
  151.  
  152. /******************************************************************************
  153.    InsertLinePartI()
  154.    This routine initiates a line creation.  It defines a cursor rectangle
  155.    for the new line.  When the user presses a mouse button, the 
  156.    InsertLinePartII function is used to create the line at the current
  157.    cursor postion.
  158. *******************************************************************************/
  159. InsertLinePartI()
  160. {
  161.    
  162.    if (CurCmd!=-1) return FALSE; // previous command not completed yet
  163.    
  164.    if (TotalItems>=MAX_ITEMS) {  // check for item table space
  165.       MessageBox(hFrWnd,"Item Table Full!",NULL,MB_OK);
  166.       return TRUE;
  167.    }
  168.  
  169.    // deselect currently selected item
  170.    if (SelItem>=0) DeselectItem();// deselect the current item
  171.  
  172.    // define the cursor rectangle
  173.    CursRect.left=FrWinOrgX+(FrWinWidth-2*DEF_RECT_WIDTH)/2;
  174.    CursRect.right=CursRect.left+2*DEF_RECT_WIDTH;
  175.    if (CursRect.right>FrWidth) {
  176.       CursRect.right=FrWidth;
  177.       CursRect.left=CursRect.right-2*DEF_RECT_WIDTH;
  178.    }
  179.    if (CursRect.left<FrWinOrgX) CursRect.left=FrWinOrgX;
  180.    if (CursRect.left>=CursRect.right) return FALSE;
  181.  
  182.    CursRect.top=FrWinOrgY+(FrWinHeight-DEF_RECT_HEIGHT)/2;
  183.    CursRect.bottom=CursRect.top+DEF_RECT_HEIGHT;
  184.    if (CursRect.bottom>FrHeight) {
  185.       CursRect.bottom=FrHeight;
  186.       CursRect.top=CursRect.bottom-DEF_RECT_HEIGHT;
  187.    }
  188.    if (CursRect.top<FrWinOrgY) CursRect.top=FrWinOrgY;
  189.    if (CursRect.top>=CursRect.bottom) return FALSE;
  190.  
  191.    // Draw the focus rectangle
  192.    FrDrawFocusRect(hFrDC,&CursRect);
  193.    FrSetCursor(CursRect.left+(CursRect.right-CursRect.left)/2,CursRect.top+(CursRect.bottom-CursRect.top)/2);
  194.    
  195.    // set the flags
  196.    CurCmd=ID_INSERT_LINE;             // current unfinished command
  197.    IgnoreMouseMove=FALSE;             // monitor mouse movements now
  198.    SelItem=-1;                        // no item selected yet
  199.  
  200.    return TRUE;
  201. }
  202.  
  203. /******************************************************************************
  204.    InsertLinePartII()
  205.    This routine finishes the line creation process started by the
  206.    InsertLinePartI function.  This function is called after the user
  207.    positions the cursor rectangle for the new line.
  208. *******************************************************************************/
  209. InsertLinePartII()
  210. {
  211.     int CurItem,CurSec;
  212.     struct StrItem NewItem;
  213.  
  214.     FrEraseFocusRect(hFrDC,&CursRect);// erase the focus rectangle
  215.     CurSec=FrAdjustCursorRect();      // adjust the cursor rectangle position
  216.     CurItem=FrFindItemSlot(CurSec);   // slot where the item will be inserted
  217.  
  218.     // initialize the NewItem
  219.     InitItem(&NewItem);            // initialize
  220.     NewItem.type=LINE;             // screen item type: LABEL,FIELD,SECTION,LINE
  221.     NewItem.x=CursRect.left;       // X position of the top/left corner of the object
  222.     NewItem.y=CursRect.top;        // Y position of the top/left coner of the object
  223.     NewItem.width=CursRect.right-CursRect.left; // width of the object 
  224.     NewItem.height=CursRect.bottom-CursRect.top;// height of the object
  225.     NewItem.section=CurSec;        // Current section
  226.  
  227.     // insert the new item
  228.     MoveItemArray(CurItem,1,'B');  // scroll down the array
  229.     HugeMove(&NewItem,&(item[CurItem]),sizeof(struct StrItem));
  230.  
  231.     // reset the flags
  232.     CurCmd=-1;                    // currnet command completed
  233.     IgnoreMouseMove=TRUE;
  234.     SetCursor(hArrowCursor);      // set the regular cursor
  235.     SelItem=CurItem;
  236.     PaintFlag=PAINT_WIN;          // to reset the option ribbon highlighting
  237.     FrPaint();                    // repaint the screen
  238.  
  239.     FrModified=TRUE;
  240.  
  241.     return TRUE;
  242. }
  243.  
  244. /******************************************************************************
  245.    InsertPicturePartI()
  246.    This routine initiates a picture insertion.  It gets the picture from
  247.    the clipboard or from the disk file.  It then defines the cursor rectangle
  248.    for the new picture. When the user presses a mouse button, the 
  249.    InsertPicturePartII function is used to insert the picture at the current
  250.    cursor postion.
  251. *******************************************************************************/
  252. InsertPicturePartI(int source)
  253. {
  254.    int PictWidth,PictHeight;
  255.    
  256.    if (CurCmd!=-1) return FALSE; // previous command not completed yet
  257.    
  258.    if (TotalItems>=MAX_ITEMS) {  // check for item table space
  259.       MessageBox(hFrWnd,"Item Table Full!",NULL,MB_OK);
  260.       return TRUE;
  261.    }
  262.  
  263.    // deselect currently selected item
  264.    if (SelItem>=0) DeselectItem();// deselect the current item
  265.  
  266.    // get the picture
  267.    if (source==ID_PICT_FROM_FILE) {
  268.       if (!PictureFromFile()) return TRUE;
  269.    }
  270.    else if (!PictureFromClipboard()) return TRUE;
  271.  
  272.    // define the cursor rectangle
  273.    PictHeight=FrFont[NewPict].height;
  274.    PictWidth=FrFont[NewPict].CharWidth[0];
  275.    
  276.    CursRect.left=FrWinOrgX+(FrWinWidth-PictWidth)/2;
  277.    CursRect.right=CursRect.left+PictWidth;
  278.    if (CursRect.right>FrWidth) {
  279.       CursRect.right=FrWidth;
  280.       CursRect.left=CursRect.right-PictWidth;
  281.    }
  282.    if (CursRect.left<FrWinOrgX) CursRect.left=FrWinOrgX;
  283.    if (CursRect.left>=CursRect.right) return FALSE;
  284.  
  285.    CursRect.top=FrWinOrgY+(FrWinHeight-PictHeight)/2;
  286.    CursRect.bottom=CursRect.top+PictHeight;
  287.    if (CursRect.bottom>FrHeight) {
  288.       CursRect.bottom=FrHeight;
  289.       CursRect.top=CursRect.bottom-PictHeight;
  290.    }
  291.  
  292.    if (CursRect.top<FrWinOrgY) CursRect.top=FrWinOrgY;
  293.    if (CursRect.top>=CursRect.bottom) return FALSE;
  294.  
  295.    // Draw the focus rectangle
  296.    FrDrawFocusRect(hFrDC,&CursRect);
  297.    FrSetCursor(CursRect.left+(CursRect.right-CursRect.left)/2,CursRect.top+(CursRect.bottom-CursRect.top)/2);
  298.    
  299.    // set the flags
  300.    CurCmd=source;                    // current unfinished command
  301.    IgnoreMouseMove=FALSE;             // monitor mouse movements now
  302.    SelItem=-1;                        // no item selected yet
  303.  
  304.    return TRUE;
  305. }
  306.  
  307. /******************************************************************************
  308.    InsertPicturePartII()
  309.    This routine finishes the picture creation process started by the
  310.    InsertPicturePartI function.  This function is called after the user
  311.    positions the cursor rectangle for the new picture.
  312. *******************************************************************************/
  313. InsertPicturePartII()
  314. {
  315.     int CurItem,CurSec;
  316.     struct StrItem NewItem;
  317.  
  318.     FrEraseFocusRect(hFrDC,&CursRect);// erase the focus rectangle
  319.     CurSec=FrAdjustCursorRect();      // adjust the cursor rectangle position
  320.     CurItem=FrFindItemSlot(CurSec);   // slot where the item will be inserted
  321.  
  322.     // initialize the NewItem
  323.     InitItem(&NewItem);            // initialize
  324.     NewItem.type=PICT;             // screen item type: LABEL,FIELD,SECTION,LINE
  325.     NewItem.x=CursRect.left;       // X position of the top/left corner of the object
  326.     NewItem.y=CursRect.top;        // Y position of the top/left coner of the object
  327.     NewItem.width=CursRect.right-CursRect.left; // width of the object 
  328.     NewItem.height=CursRect.bottom-CursRect.top;// height of the object
  329.     NewItem.section=CurSec;        // Current section
  330.     NewItem.font=NewPict;          // index into the font/picture table
  331.  
  332.     // insert the new item
  333.     MoveItemArray(CurItem,1,'B');  // scroll down the array
  334.     HugeMove(&NewItem,&(item[CurItem]),sizeof(struct StrItem));
  335.  
  336.     // reset the flags
  337.     CurCmd=-1;                    // currnet command completed
  338.     IgnoreMouseMove=TRUE;
  339.     SetCursor(hArrowCursor);      // set the regular cursor
  340.     SelItem=CurItem;
  341.     FrPaint();                    // repaint the screen
  342.  
  343.     FrModified=TRUE;
  344.  
  345.     return TRUE;
  346. }
  347.  
  348. /******************************************************************************
  349.    InsertFieldPartI:
  350.    This routine initiates a field insertion.  It gets the field name from
  351.    the field creation functions.  It then defines the cursor rectangle
  352.    for the new field. When the user presses a mouse button, the 
  353.    InsertFieldPartII function is used to insert the field at the current
  354.    cursor postion.
  355. *******************************************************************************/
  356. InsertFieldPartI(int type)
  357. {
  358.    int FieldWidth,FieldHeight;
  359.    BOOL result;
  360.    char label[LINE_WIDTH+1];
  361.    MSG  msg;
  362.  
  363.    if (CurCmd!=-1) return FALSE; // previous command not completed yet
  364.    
  365.    if (TotalItems>=MAX_ITEMS) {  // check for item table space
  366.       MessageBox(hFrWnd,"Item Table Full!",NULL,MB_OK);
  367.       return TRUE;
  368.    }
  369.  
  370.    // deselect currently selected item
  371.    if (SelItem>=0) DeselectItem();// deselect the current item
  372.  
  373.    // get the field name in the field array
  374.    switch (type) {
  375.       case ID_INSERT_DATA:
  376.          result=InsertDataField();break;
  377.       case ID_INSERT_CALC:
  378.          result=InsertCalcField();break;
  379.       case ID_INSERT_SYS:
  380.          result=InsertSysField();break;
  381.       case ID_INSERT_DLG:
  382.          result=InsertDlgField();break;
  383.    }
  384.    // discard any mouse messages left from the above call
  385.    while (PeekMessage(&msg,hFrWnd,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE|PM_NOYIELD));;
  386.    if (!result) {                   // user cancelled the operation
  387.       PaintFlag=PAINT_WIN;          // to reset the option ribbon highlighting
  388.       FrPaint();
  389.       return FALSE;
  390.    }
  391.  
  392.    // find default field width/height
  393.    CreateFieldLabel(NewField,label,0,DEFAULT_CFMT);
  394.    FieldWidth=GetLabelLen(label,DEFAULT_CFMT)+2*DESC_MARGIN;
  395.    FieldHeight=DEF_RECT_HEIGHT;
  396.    if (field[NewField].type==TYPE_PICT) FieldHeight=FieldWidth;
  397.  
  398.    // define the cursor rectangle
  399.    CursRect.left=FrWinOrgX+(FrWinWidth-FieldWidth)/2;
  400.    CursRect.right=CursRect.left+FieldWidth;
  401.    if (CursRect.right>FrWidth) {
  402.       CursRect.right=FrWidth;
  403.       CursRect.left=CursRect.right-FieldWidth;
  404.    }
  405.    if (CursRect.left<FrWinOrgX) CursRect.left=FrWinOrgX;
  406.    if (CursRect.left>=CursRect.right) return FALSE;
  407.  
  408.    CursRect.top=FrWinOrgY+(FrWinHeight-FieldHeight)/2;
  409.    CursRect.bottom=CursRect.top+FieldHeight;
  410.    if (CursRect.bottom>FrHeight) {
  411.       CursRect.bottom=FrHeight;
  412.       CursRect.top=CursRect.bottom-FieldHeight;
  413.    }
  414.  
  415.    if (CursRect.top<FrWinOrgY) CursRect.top=FrWinOrgY;
  416.    if (CursRect.top>=CursRect.bottom) return FALSE;
  417.  
  418.    // Draw the focus rectangle
  419.    FrDrawFocusRect(hFrDC,&CursRect);
  420.    FrSetCursor(CursRect.left+(CursRect.right-CursRect.left)/2,CursRect.top+(CursRect.bottom-CursRect.top)/2);
  421.    
  422.    // set the flags
  423.    CurCmd=type;                       // current unfinished command
  424.    IgnoreMouseMove=FALSE;             // monitor mouse movements now
  425.    SelItem=-1;                        // no item selected yet
  426.  
  427.    return TRUE;
  428. }
  429.  
  430. /******************************************************************************
  431.    InsertFieldPartII()
  432.    This routine finishes the field creation process started by the
  433.    InsertFieldPartI function.  This function is called after the user
  434.    positions the cursor rectangle for the new field.
  435. *******************************************************************************/
  436. InsertFieldPartII()
  437. {
  438.     int CurItem,CurSec;
  439.     struct StrItem NewItem;
  440.     struct StrField huge *pField;
  441.  
  442.     FrEraseFocusRect(hFrDC,&CursRect);// erase the focus rectangle
  443.     CurSec=FrAdjustCursorRect();      // adjust the cursor rectangle position
  444.     CurItem=FrFindItemSlot(CurSec);   // slot where the item will be inserted
  445.  
  446.     // initialize the NewItem
  447.     InitItem(&NewItem);            // initialize
  448.     NewItem.type=FIELD;            // screen item type: LABEL,FIELD,SECTION,LINE
  449.     NewItem.x=CursRect.left;       // X position of the top/left corner of the object
  450.     NewItem.y=CursRect.top;        // Y position of the top/left coner of the object
  451.     NewItem.width=CursRect.right-CursRect.left; // width of the object 
  452.     NewItem.height=CursRect.bottom-CursRect.top;// height of the object
  453.     NewItem.section=CurSec;        // Current section
  454.     NewItem.field=NewField;        // index into the field table
  455.     CreateFieldLabel(NewField,NewItem.label,NewItem.width,NewItem.font);  // create field label
  456.  
  457.     pField=&field[NewField];
  458.     if (pField->type==TYPE_NUM || pField->type==TYPE_DBL) {
  459.        NewItem.flags=NewItem.flags&(~((UINT)OFLAG_HLEFT|OFLAG_HCENTER)); // reset flags
  460.        NewItem.flags=NewItem.flags|OFLAG_HRIGHT;
  461.        if (CurSec>=SEC_FTR_LVL9 && pField->source!=SRC_SYS) pField->SumType=SUM_TOTAL;
  462.     }
  463.     else if (pField->type==TYPE_PICT) {
  464.       NewItem.OutlineSelect=OUTLINE_LEFT|OUTLINE_RIGHT|OUTLINE_TOP|OUTLINE_BOT;
  465.     }
  466.  
  467.     // insert the new item
  468.     MoveItemArray(CurItem,1,'B');  // scroll down the array
  469.     HugeMove(&NewItem,&(item[CurItem]),sizeof(struct StrItem));
  470.  
  471.     // reset the flags
  472.     CurCmd=-1;                    // currnet command completed
  473.     IgnoreMouseMove=TRUE;
  474.     SetCursor(hArrowCursor);      // set the regular cursor
  475.     SelItem=CurItem;
  476.     PaintFlag=PAINT_WIN;          // to reset the option ribbon highlighting
  477.     FrPaint();                    // repaint the screen
  478.  
  479.     FrModified=TRUE;
  480.  
  481.     return TRUE;
  482. }
  483.  
  484. /******************************************************************************
  485.    UpdateLabelText:
  486.    This routine is called when the user edits the label text.  This
  487.    routine updates the current label text from the description window.
  488. *******************************************************************************/
  489. UpdateLabelText()
  490. {
  491.    char string[LINE_WIDTH+1];
  492.  
  493.  
  494.    if (SelItem<0 || !hDescWnd) return TRUE;  // not applicable
  495.    if (item[SelItem].type!=LABEL) return TRUE;
  496.  
  497.    GetWindowText(hDescWnd,string,LINE_WIDTH);
  498.    string[LINE_WIDTH]=0;
  499.  
  500.    if (lstrcmp(string,item[SelItem].label)!=0) {  // text changed
  501.       lstrcpy(item[SelItem].label,string);
  502.       
  503.       UpdateLabelSize(SelItem);
  504.  
  505.       // clear the item background and redraw the item
  506.       FrEraseFocusRect(hFrDC,&CursRect);
  507.       
  508.       FrPaint();
  509.       FrModified=TRUE;
  510.    }
  511.    return TRUE;
  512. }
  513.  
  514. /******************************************************************************
  515.    UpdateLabelSize:
  516.    This routine updates the label rectangle size for the current label string
  517.    and font index.  The size is not changed for an empty rectangle or rectangle
  518.    whose size was changed by the user by using item size function.
  519. *******************************************************************************/
  520. UpdateLabelSize(int CurItem)
  521. {
  522.    int font;
  523.    
  524.    if (item[CurItem].type!=LABEL) return TRUE;
  525.    if (lstrlen(item[CurItem].label)==0) return TRUE;  // do size the blank label
  526.    if (item[CurItem].sized) return TRUE;  // do not change the manually sized item
  527.  
  528.    font=item[CurItem].font;
  529.    item[CurItem].width=GetLabelLen(item[CurItem].label,font)+2*DESC_MARGIN;
  530.    item[CurItem].height=FrFont[font].height;
  531.  
  532.    return TRUE;
  533. }
  534.  
  535. /******************************************************************************
  536.    MoveItem()
  537.    This routine is called when a mouse button is release as a screen item
  538.    is being moved.  When a group item is being relocated, this routine calls
  539.    the MoveEachItem routine to move each item of the group.
  540. *******************************************************************************/
  541. MoveItem()
  542. {
  543.     int i,DeltaX,DeltaY;
  544.  
  545.     if (SelItem<0) return FALSE;
  546.  
  547.     FrEraseFocusRect(hFrDC,&CursRect);// erase the focus rectangle
  548.     
  549.     if (item[SelItem].type!=GROUP) FrAdjustCursorRect(); // adjust the cursor rectangle position
  550.  
  551.     // calculate the amount of location
  552.     DeltaX=CursRect.left-item[SelItem].x;
  553.     DeltaY=CursRect.top-item[SelItem].y;
  554.  
  555.     // check if the item location has changed
  556.     if ( (DeltaX==0 || abs(DeltaX)<(UNITS_PER_INCH/ResX))
  557.       && (DeltaY==0 || abs(DeltaY)<(UNITS_PER_INCH/ResY)) ){
  558.        PaintFlag=PAINT_ITEMS;         // do not refresh entire window
  559.        goto END;
  560.     }
  561.     else DiscardUndo();               // discard previous undo
  562.  
  563.     // process the group item
  564.     if (item[SelItem].type==GROUP) {
  565.         // flag the items within this group
  566.         MarkGroupItems();
  567.  
  568.         // move the group item
  569.         MoveEachItem(SelItem,DeltaX,DeltaY);
  570.         
  571.         // move each item within the group
  572.         while (TRUE) {
  573.            // find an item in the group
  574.            for(i=0;i<TotalItems;i++) if (item[i].InGroup) break;
  575.            if (i==TotalItems) break;  // all items processed
  576.            item[i].InGroup=FALSE;     // reset flag for this item
  577.            MoveEachItem(i,DeltaX,DeltaY);
  578.         }
  579.         
  580.         // locate the group item
  581.         for (i=0;i<TotalItems;i++) if (item[i].type==GROUP) break;
  582.         if (i<TotalItems) SelItem=i;
  583.         else AbortFr("Group Item Missing(MoveItem)",ERR_OTHER);
  584.     }
  585.     else {                            // process the non group item
  586.         SelItem=MoveEachItem(SelItem,DeltaX,DeltaY);
  587.     }
  588.  
  589.     FrModified=TRUE;
  590.  
  591.     END:
  592.     // reset the flags
  593.     CurCmd=-1;                    // currnet command completed
  594.     IgnoreMouseMove=TRUE;
  595.     SetCursor(hArrowCursor);      // set the regular cursor
  596.     
  597.     FrPaint();                    // repaint the screen
  598.  
  599.     return TRUE;
  600. }
  601.  
  602. /******************************************************************************
  603.    MoveEachItem()
  604.    This routine is called by the MoveItem routine to move one item of
  605.    the group item. This routine returns the new item index.
  606. *******************************************************************************/
  607. MoveEachItem(int OrigItem,int DeltaX,int DeltaY)
  608. {
  609.     int CurItem,CurSec,i;
  610.     struct StrItem NewItem;
  611.     struct StrField huge *pField;
  612.  
  613.     if (DeltaX==0 && DeltaY==0) return OrigItem;  // no need to move
  614.  
  615.     // Initialize the NewItem
  616.     HugeMove(&item[OrigItem],&NewItem,sizeof(struct StrItem));
  617.     NewItem.x+=DeltaX;       // X position of the top/left corner of the object
  618.     NewItem.y+=DeltaY;       // Y position of the top/left coner of the object
  619.     
  620.     // make sure the object lies within a section
  621.     if (item[OrigItem].type!=GROUP) {
  622.        MakeRect(&CursRect,NewItem.x,NewItem.y,NewItem.width,NewItem.height);
  623.        CurSec=FrAdjustCursorRect();  // adjust the cursor rectangle position
  624.        NewItem.x=CursRect.left;
  625.        NewItem.y=CursRect.top;
  626.        NewItem.width=CursRect.right-CursRect.left;
  627.        NewItem.height=CursRect.bottom-CursRect.top;
  628.     }
  629.     else {                   // find section where the group item lies
  630.        for (i=0;i<TotalItems;i++) if (item[i].y>NewItem.y) break;
  631.        if (i>0) CurSec=item[i-1].section;
  632.        else     CurSec=item[0].section;
  633.     }
  634.  
  635.     // Insert the item in the item array 
  636.     CurItem=FrFindItemSlot(CurSec);// sorted slot where the item will be inserted
  637.     
  638.     NewItem.section=CurSec;        
  639.     
  640.     // adjustment for field type items
  641.     if (NewItem.type==FIELD) {
  642.        pField=&field[NewItem.field];
  643.        if (CurSec>=SEC_FTR_LVL9 && item[OrigItem].section<SEC_FTR_LVL9) {
  644.           if ((pField->type==TYPE_NUM || pField->type==TYPE_DBL) 
  645.            && pField->source!=SRC_SYS) pField->SumType=SUM_TOTAL;
  646.        }
  647.        if (CurSec<SEC_FTR_LVL9) pField->SumType=SUM_NONE;
  648.     }
  649.     
  650.     // Insert the modified item
  651.     MoveItemArray(CurItem,1,'B');  // scroll down the array
  652.     HugeMove(&NewItem,&(item[CurItem]),sizeof(struct StrItem));
  653.     if (OrigItem>=CurItem) OrigItem++; // scrolled down
  654.  
  655.     // delete the old item
  656.     MoveItemArray(OrigItem,1,'D');    // delete the old item
  657.     if (OrigItem<CurItem) CurItem--;  // scroll down
  658.  
  659.     return CurItem;
  660. }
  661.  
  662. /******************************************************************************
  663.    SizeItem()
  664.    This routine is called when a mouse button is release as a screen item
  665.    is being sized.
  666. *******************************************************************************/
  667. SizeItem()
  668. {
  669.     int CurItem,CurSec;
  670.     struct StrItem NewItem;
  671.  
  672.     if (item[SelItem].type==SECTION) return SizeSection();
  673.  
  674.     FrEraseFocusRect(hFrDC,&CursRect);// erase the focus rectangle
  675.     CurSec=FrAdjustCursorRect();      // adjust the cursor rectangle position
  676.  
  677.     // Initialize the NewItem
  678.     HugeMove(&item[SelItem],&NewItem,sizeof(struct StrItem));
  679.     NewItem.x=CursRect.left;       // X position of the top/left corner of the object
  680.     NewItem.y=CursRect.top;        // Y position of the top/left coner of the object
  681.     NewItem.width=CursRect.right-CursRect.left;
  682.     NewItem.height=CursRect.bottom-CursRect.top;
  683.     if (NewItem.width<1)  NewItem.width=1;
  684.     if (NewItem.height<1) NewItem.height=1;
  685.     NewItem.sized=TRUE;            // mark as manually sized
  686.     if (NewItem.type==FIELD) CreateFieldLabel(NewItem.field,NewItem.label,NewItem.width,NewItem.font);
  687.  
  688.     // Insert the item in the item array 
  689.     CurItem=FrFindItemSlot(CurSec);// sorted slot where the item will be inserted
  690.     
  691.     NewItem.section=CurSec;        
  692.  
  693.     // Insert the modified item
  694.     MoveItemArray(CurItem,1,'B');  // scroll down the array
  695.     HugeMove(&NewItem,&(item[CurItem]),sizeof(struct StrItem));
  696.     if (SelItem>=CurItem) SelItem++; // scrolled down
  697.  
  698.     // delete the old item
  699.     MoveItemArray(SelItem,1,'D');    // delete the old item
  700.     if (SelItem<CurItem) CurItem--;  // scroll down
  701.     SelItem=CurItem;                 // now select the new item
  702.  
  703.     // END
  704.     // reset the flags
  705.     CurCmd=-1;                    // currnet command completed
  706.     IgnoreMouseMove=TRUE;
  707.     SetCursor(hArrowCursor);      // set the regular cursor
  708.     FrPaint();                    // repaint the screen
  709.     
  710.     FrModified=TRUE;
  711.  
  712.     return TRUE;
  713. }
  714.  
  715. /******************************************************************************
  716.    SizeSection()
  717.    This routine is called when a mouse button is release as a screen section
  718.    is being sized.
  719. *******************************************************************************/
  720. SizeSection()
  721. {
  722.     int CurSec,i,MinY,MaxY,AdjHeight,AdjY;
  723.     struct StrItem NewItem;
  724.  
  725.     FrEraseFocusRect(hFrDC,&CursRect);// erase the focus rectangle
  726.  
  727.     CurSec=item[SelItem].section;  // current section
  728.  
  729.     // Find height of items within this section
  730.     MinY=MaxY=-1;
  731.     for (i=SelItem+1;i<TotalItems;i++) {
  732.        if (item[i].section!=CurSec) break;
  733.        if (item[i].type==GROUP) continue;  // do not consider group item for this calculation
  734.        if (MinY==-1) MinY=item[i].y;
  735.        if (item[i].y<MinY) MinY=item[i].y;
  736.        if (MaxY==-1) MaxY=item[i].y+item[i].height;
  737.        if ((item[i].y+item[i].height)>MaxY) MaxY=item[i].y+item[i].height;
  738.     }
  739.     if (MinY!=-1) {                        // adjust the cursor rectabgle
  740.        MinY-=FormHdr.SecBannerHeight;      // reduce by the section banner height
  741.        if (CursRect.top>=MinY) CursRect.top=MinY-1;
  742.        if (CursRect.bottom<=MaxY) CursRect.bottom=MaxY+1;
  743.     }
  744.  
  745.     // Initialize the NewItem
  746.     HugeMove(&item[SelItem],&NewItem,sizeof(struct StrItem));
  747.  
  748.     NewItem.y=CursRect.top;        // Y position of the top/left coner of the object
  749.     NewItem.height=CursRect.bottom-CursRect.top;
  750.     if (NewItem.height<(3*FormHdr.SecBannerHeight/2)) NewItem.height=3*FormHdr.SecBannerHeight/2;
  751.  
  752.     // Update the section object
  753.     AdjY=NewItem.y-item[SelItem].y;                // Y adjustment
  754.     AdjHeight=NewItem.height-item[SelItem].height; // height adjustment
  755.     FrHeight+=AdjHeight;                           // update the form height
  756.     HugeMove(&NewItem,&(item[SelItem]),sizeof(struct StrItem));
  757.  
  758.     // update the Y position of items within the current section
  759.     for (i=SelItem;i<TotalItems;i++) {
  760.        if (item[i].section>CurSec) break;
  761.        item[i].y-=AdjY;                // adjust the height
  762.        if (i>SelItem) {                // bound check
  763.           if (item[i].y>=item[SelItem].y+item[SelItem].height) 
  764.              item[i].y=item[SelItem].y+item[SelItem].height-1;
  765.           if (item[i].y<item[SelItem].y+FormHdr.SecBannerHeight) 
  766.              item[i].y=item[SelItem].y+FormHdr.SecBannerHeight;
  767.        }
  768.     }
  769.  
  770.     // Update the y position of items in the subsequent sections
  771.     for (i=SelItem;i<TotalItems;i++) {
  772.        if (item[i].section==CurSec) continue;
  773.        item[i].y+=AdjHeight;               // adjust the height
  774.     }
  775.  
  776.     // END
  777.     // reset the flags
  778.     CurCmd=-1;                    // currnet command completed
  779.     IgnoreMouseMove=TRUE;
  780.     SetCursor(hArrowCursor);      // set the regular cursor
  781.     FrPaint();                    // repaint the screen
  782.  
  783.     FrModified=TRUE;
  784.  
  785.     return TRUE;
  786. }
  787.  
  788. /******************************************************************************
  789.     DeleteItem:
  790.     Delete the current item. The current item must not be a 'section' type
  791.     item.
  792. ******************************************************************************/
  793. DeleteItem()
  794. {      
  795.     int group=FALSE,CurItem;
  796.  
  797.     if (SelItem<0) return TRUE;   // no item selected
  798.     if (item[SelItem].type==SECTION) return DeleteSection();
  799.  
  800.     if (item[SelItem].type==GROUP) {
  801.        MarkGroupItems();          // mark the items in the group
  802.        group=TRUE;
  803.     }
  804.  
  805.     while (TRUE) {               // delete each item
  806.        if (group) CurItem=NextGroupItem();
  807.        else       CurItem=SelItem;
  808.        if (CurItem<0) break;     // all items processed
  809.     
  810.        if (item[CurItem].type==LINE || item[CurItem].type==LABEL) MoveItemArray(CurItem,1,'D');
  811.        else if (item[CurItem].type==PICT) {
  812.           DeleteFrObject(item[CurItem].font);   // delete the font/picture object
  813.           MoveItemArray(CurItem,1,'D');         // delete and scroll the item array
  814.        }
  815.        else if (item[CurItem].type==FIELD) {
  816.           DeleteField(item[CurItem].field);     // delete the field object from the field array
  817.           MoveItemArray(CurItem,1,'D');         // delete and scroll the item array
  818.        }
  819.  
  820.        if (!group) break;        // only one item to process
  821.     }
  822.  
  823.     FrEraseFocusRect(hFrDC,&CursRect);
  824.     SelItem=-1;                  // disable all sections
  825.     FrPaint();
  826.     FrModified=TRUE;
  827.     
  828.     return TRUE;
  829. }
  830.  
  831. /******************************************************************************
  832.     PosItem:
  833.     Position the item text inside the item outlines.
  834. ******************************************************************************/
  835. PosItem()
  836. {      
  837.     int result,i,GroupItem;
  838.     UINT flags,mask;
  839.  
  840.     if (SelItem<0) return TRUE;   // no item selected
  841.     if (item[SelItem].type!=LABEL && item[SelItem].type!=FIELD && item[SelItem].type!=GROUP) return TRUE; // applicable to label and field only
  842.     if (item[SelItem].type==FIELD && field[item[SelItem].field].type==TYPE_PICT) return TRUE;  // picture type item does not use font
  843.  
  844.  
  845.     result=CallDialogBox("PosParam",PosParam,0L);
  846.     if (result) {
  847.        if (item[SelItem].type==GROUP) {  // update all items in the group
  848.           GroupItem=SelItem;
  849.           MarkGroupItems();       // mark the items in the group
  850.           // make a mask for the flags to be changed
  851.           mask=OFLAG_HLEFT|OFLAG_HRIGHT|OFLAG_HCENTER|OFLAG_VTOP|OFLAG_VBOTTOM|OFLAG_VCENTER;
  852.           flags=item[GroupItem].flags&mask;
  853.           mask=~mask;
  854.           for (i=0;i<TotalItems;i++) {
  855.               if (item[i].InGroup) {
  856.                  if (item[i].type!=LABEL || item[i].type!=FIELD) {
  857.                      item[i].flags=(item[i].flags&mask)|flags;
  858.                  }
  859.                  item[i].InGroup=FALSE;
  860.               }
  861.           }
  862.        }
  863.  
  864.        FrPaint();
  865.        FrModified=TRUE;
  866.     }
  867.  
  868.     return TRUE;
  869. }
  870.  
  871. /******************************************************************************
  872.     EditLine:
  873.     Edit current line property
  874. ******************************************************************************/
  875. EditLine()
  876. {      
  877.     int result;
  878.  
  879.     if (SelItem<0 || item[SelItem].type!=LINE) return TRUE;   // no item selected
  880.  
  881.     result=CallDialogBox("LineParam",LineParam,0L);
  882.     if (result) {
  883.        FrPaint();
  884.        FrModified=TRUE;
  885.     }
  886.  
  887.     return TRUE;
  888. }
  889.  
  890. /******************************************************************************
  891.     EditItemOutline:
  892.     Edit the item outline style and color
  893. ******************************************************************************/
  894. EditItemOutline()
  895. {      
  896.     int result,i,GroupItem;
  897.  
  898.     if (SelItem<0) return TRUE;   // no item selected
  899.  
  900.     result=CallDialogBox("OutlineParam",OutlineParam,0L);
  901.     if (result) {
  902.        if (item[SelItem].type==GROUP) {  // update all items in the group
  903.           GroupItem=SelItem;
  904.           MarkGroupItems();       // mark the items in the group
  905.           for (i=0;i<TotalItems;i++) {
  906.             if (item[i].InGroup) {
  907.                item[i].OutlineSelect=item[GroupItem].OutlineSelect;
  908.                item[i].OutlineStyle =item[GroupItem].OutlineStyle;
  909.                item[i].OutlineWidth =item[GroupItem].OutlineWidth;
  910.                item[i].OutlineColor =item[GroupItem].OutlineColor;
  911.                item[i].InGroup=FALSE;
  912.             }
  913.           }
  914.        }
  915.  
  916.        FrPaint();
  917.        FrModified=TRUE;
  918.     }
  919.  
  920.  
  921.     return TRUE;
  922. }
  923.  
  924. /******************************************************************************
  925.     EditItemBackground:
  926.     Edit the item background paiting brush
  927. ******************************************************************************/
  928. EditItemBackground()
  929. {      
  930.     int result,i,GroupItem;
  931.     UINT flags,mask;
  932.  
  933.     if (SelItem<0) return TRUE;   // no item selected
  934.     if (item[SelItem].type==PICT) return TRUE;  // not applicable for picture type objects
  935.  
  936.     result=CallDialogBox("BackgroundParam",BackgroundParam,0L);
  937.     if (result) {
  938.        if (item[SelItem].type==GROUP) {  // update all items in the group
  939.           GroupItem=SelItem;
  940.           MarkGroupItems();       // mark the items in the group
  941.           // make a mask for the flags to be changed
  942.           mask=OFLAG_FILL;
  943.           flags=item[GroupItem].flags&mask;
  944.           mask=~mask;
  945.           for (i=0;i<TotalItems;i++) {
  946.              if (item[i].InGroup) {
  947.                 if (item[i].type!=PICT) {    // N/A
  948.                    item[i].flags=(item[i].flags&mask)|flags;
  949.                    HugeMove(&(item[GroupItem].brush),&(item[i].brush),sizeof(LOGBRUSH));
  950.                 }
  951.                 item[i].InGroup=FALSE;
  952.              }
  953.           }
  954.        }
  955.        FrPaint();
  956.        FrModified=TRUE;
  957.     }
  958.     return TRUE;
  959. }
  960.  
  961. /******************************************************************************
  962.     CenterItem:
  963.     Center the selected item horizontally.
  964. *******************************************************************************/
  965. CenterItem()
  966. {
  967.     int  CurSec,SecItem;
  968.     RECT rect;
  969.  
  970.     if (SelItem<0 || item[SelItem].type==SECTION) return TRUE;
  971.  
  972.     // get the current section
  973.     CurSec=item[SelItem].section;
  974.     SecItem=section[CurSec].ScrItem;
  975.  
  976.     // build the new item position
  977.     rect.left=item[SecItem].x+(item[SecItem].width-item[SelItem].width)/2;
  978.     rect.right=rect.left+item[SelItem].width;
  979.     rect.top=item[SelItem].y;
  980.     rect.bottom=rect.top+item[SelItem].height;
  981.  
  982.     // scroll the screen if necessary
  983.     FrEraseFocusRect(hFrDC,&CursRect);
  984.     FarMove(&rect,&CursRect,sizeof(RECT));
  985.     FrAdjustScroll(&CursRect);
  986.     MoveItem();                      // move the item to the new location
  987.  
  988.     return TRUE;
  989. }
  990.  
  991. /******************************************************************************
  992.    SelectGroupItemPartI()
  993.    This routine initiates group item selection.  It defines a cursor rectangle
  994.    for the group item.  When the user releases the mouse button, the 
  995.    SelectGroupItemPartII function is used to position the group item
  996.    rectangle at the current location.
  997. *******************************************************************************/
  998. SelectGroupItemPartI(int x,int y)
  999. {
  1000.    if (MouseX==x && MouseY==y) return TRUE;  // no mouse movement yet
  1001.  
  1002.    // deselect currently selected item
  1003.    if (SelItem>=0) DeselectItem();           // deselect the current item
  1004.  
  1005.    // define the cursor rectangle
  1006.    CursRect.left=MouseX;
  1007.    CursRect.right=x;
  1008.    CursRect.top=MouseY;
  1009.    CursRect.bottom=y;
  1010.  
  1011.    // Draw the focus rectangle
  1012.    FrDrawFocusRect(hFrDC,&CursRect);
  1013.    
  1014.    // set the flags
  1015.    CurCmd=ID_SELECT_MULTIPLE;         // current unfinished command
  1016.    IgnoreMouseMove=FALSE;             // monitor mouse movements now
  1017.    SelItem=-1;                        // no item selected yet
  1018.    CurTab=TAB_SE;                     // let the rectangle be stretched
  1019.  
  1020.    return TRUE;
  1021. }
  1022.  
  1023. /******************************************************************************
  1024.     SelectGroupItemPartII:
  1025.     This routine is called when the group item cursor is clicked.  It position
  1026.     the group item at the current cursor location.    
  1027. *******************************************************************************/
  1028. SelectGroupItemPartII()
  1029. {
  1030.     int CurItem,CurSec,GroupItem,i;
  1031.     struct StrItem NewItem;
  1032.  
  1033.     // locate the previous group item
  1034.     for (GroupItem=0;GroupItem<TotalItems;GroupItem++) if (item[GroupItem].type==GROUP) break;
  1035.     if (GroupItem>=TotalItems) AbortFr("Group Item Missing",ERR_OTHER);
  1036.  
  1037.     // make a copy of the previous group item and delete previous group item
  1038.     HugeMove(&item[GroupItem],&NewItem,sizeof(struct StrItem));
  1039.     MoveItemArray(GroupItem,1,'D');   // delete this item
  1040.  
  1041.     // find the location for the new group item
  1042.     FrEraseFocusRect(hFrDC,&CursRect);// erase the focus rectangle
  1043.     CurSec=FrAdjustCursorRect();      // adjust the cursor rectangle position
  1044.     CurItem=FrFindItemSlot(CurSec);   // slot where the item will be inserted
  1045.  
  1046.     // assign the group item fields.
  1047.     if (CursRect.left<CursRect.right) {
  1048.        NewItem.x=CursRect.left;          // X position of the top/left corner of the object
  1049.        NewItem.width=CursRect.right-CursRect.left; // width of the object 
  1050.     }
  1051.     else {
  1052.        NewItem.x=CursRect.right;         // X position of the top/left corner of the object
  1053.        NewItem.width=CursRect.left-CursRect.right; // width of the object 
  1054.     }
  1055.     if (CursRect.top<CursRect.bottom) {
  1056.        NewItem.y=CursRect.top;           // Y position of the top/left coner of the object
  1057.        NewItem.height=CursRect.bottom-CursRect.top;// height of the object
  1058.     }
  1059.     else {
  1060.        NewItem.y=CursRect.bottom;        // Y position of the top/left coner of the object
  1061.        NewItem.height=CursRect.top-CursRect.bottom;// height of the object
  1062.     }
  1063.     NewItem.section=CurSec;           // Current section
  1064.     
  1065.     MoveItemArray(CurItem,1,'B');     // scroll down the array
  1066.     HugeMove(&NewItem,&(item[CurItem]),sizeof(struct StrItem));
  1067.     SelItem=CurItem;                  // select the current group item
  1068.     // Do not select very small selection rectangle
  1069.     if (NewItem.width<=DESC_MARGIN && NewItem.height<=DESC_MARGIN) { 
  1070.        CurSec=item[SelItem].section;
  1071.        SelItem=section[CurSec].ScrItem;
  1072.     }
  1073.  
  1074.     // reset the item selection flag
  1075.     for (i=0;i<TotalItems;i++) item[i].flags=ResetUintFlag(item[i].flags,OFLAG_SELECT_TOGGLE);
  1076.  
  1077.     CurCmd=-1;                        // currnet command completed
  1078.     IgnoreMouseMove=TRUE;
  1079.     SetCursor(hArrowCursor);          // set the regular cursor
  1080.     FrPaint();                        // repaint the screen
  1081.  
  1082.     return TRUE;
  1083. }
  1084.  
  1085. /******************************************************************************
  1086.    AlignHorzTop:
  1087.    Align horizontally at the top edge of the selected items.    
  1088. *******************************************************************************/
  1089. void AlignHorzTop()
  1090. {
  1091.    int i,LeadItem,DeltaVal,CurItem,FixVal;
  1092.    
  1093.    // exit if a group item not selected
  1094.    if (SelItem<0 || item[SelItem].type!=GROUP) return;
  1095.  
  1096.    StoreUndo();                 // store the undo data
  1097.  
  1098.    MarkGroupItems();            // mark the items in this group
  1099.  
  1100.    // find the lead item as the leftmost item
  1101.    if ((LeadItem=LeftMostItem())<0) return;
  1102.    item[LeadItem].InGroup=FALSE; // do not move the lead item
  1103.    FixVal=item[LeadItem].y;      // set at this value
  1104.  
  1105.    // do the alignment
  1106.    while(TRUE) {
  1107.      if ((CurItem=NextGroupItem())<0) break;    // all items processed
  1108.      DeltaVal=FixVal-item[CurItem].y;           // amount of adjustment
  1109.      MoveEachItem(CurItem,0,DeltaVal);
  1110.    }
  1111.  
  1112.    // find the group item
  1113.    for (i=0;i<TotalItems;i++) if (item[i].type==GROUP) break;
  1114.    if (i<TotalItems) SelItem=i;
  1115.    FrModified=TRUE;
  1116.    FrPaint();                   // refresh the screen
  1117. }
  1118.  
  1119. /******************************************************************************
  1120.    AlignHorzBot:
  1121.    Align horizontally at the bottom edge of the selected items.    
  1122. *******************************************************************************/
  1123. void AlignHorzBot()
  1124. {
  1125.    int i,LeadItem,DeltaVal,CurItem,FixVal;
  1126.    
  1127.    // exit if a group item not selected
  1128.    if (SelItem<0 || item[SelItem].type!=GROUP) return;
  1129.  
  1130.    StoreUndo();                 // store the undo data
  1131.  
  1132.    MarkGroupItems();            // mark the items in this group
  1133.  
  1134.    // find the lead item as the leftmost item
  1135.    if ((LeadItem=LeftMostItem())<0) return;
  1136.    item[LeadItem].InGroup=FALSE; // do not move the lead item
  1137.    FixVal=item[LeadItem].y+item[LeadItem].height; // set at this value
  1138.  
  1139.    // do the alignment
  1140.    while(TRUE) {
  1141.      if ((CurItem=NextGroupItem())<0) break;    // all items processed
  1142.      DeltaVal=FixVal-(item[CurItem].y+item[CurItem].height); // amount of adjustment
  1143.      MoveEachItem(CurItem,0,DeltaVal);
  1144.    }
  1145.  
  1146.    // find the group item
  1147.    for (i=0;i<TotalItems;i++) if (item[i].type==GROUP) break;
  1148.    if (i<TotalItems) SelItem=i;
  1149.    FrModified=TRUE;
  1150.    FrPaint();                   // refresh the screen
  1151. }
  1152.  
  1153. /******************************************************************************
  1154.    AlignHorzCenter:
  1155.    Align horizontally at the center line of the selected items.    
  1156. *******************************************************************************/
  1157. void AlignHorzCenter()
  1158. {
  1159.    int i,LeadItem,DeltaVal,FixVal,CurItem;
  1160.    
  1161.    // exit if a group item not selected
  1162.    if (SelItem<0 || item[SelItem].type!=GROUP) return;
  1163.    
  1164.    StoreUndo();                 // store the undo data
  1165.  
  1166.    MarkGroupItems();            // mark the items in this group
  1167.  
  1168.    // find the lead item as the leftmost item
  1169.    if ((LeadItem=LeftMostItem())<0) return;
  1170.    item[LeadItem].InGroup=FALSE; // do not move the lead item
  1171.    FixVal=item[LeadItem].y+item[LeadItem].height/2; // set at this value
  1172.  
  1173.    // do the alignment
  1174.    while(TRUE) {
  1175.      if ((CurItem=NextGroupItem())<0) break;    // all items processed
  1176.      DeltaVal=FixVal-(item[CurItem].y+item[CurItem].height/2); // amount of adjustment
  1177.      MoveEachItem(CurItem,0,DeltaVal);
  1178.    }
  1179.    
  1180.    // find the group item
  1181.    for (i=0;i<TotalItems;i++) if (item[i].type==GROUP) break;
  1182.    if (i<TotalItems) SelItem=i;
  1183.    FrModified=TRUE;
  1184.    FrPaint();                   // refresh the screen
  1185. }
  1186.  
  1187. /******************************************************************************
  1188.    AlignVertLeft:
  1189.    Align vertically at the left edge of the selected items.    
  1190. *******************************************************************************/
  1191. void AlignVertLeft()
  1192. {
  1193.    int i,LeadItem,DeltaVal,CurItem,FixVal;
  1194.    
  1195.    // exit if a group item not selected
  1196.    if (SelItem<0 || item[SelItem].type!=GROUP) return;
  1197.    
  1198.    StoreUndo();                 // store the undo data
  1199.  
  1200.    MarkGroupItems();            // mark the items in this group
  1201.  
  1202.    // find the lead item as the topmost item
  1203.    if ((LeadItem=TopMostItem())<0) return;
  1204.    item[LeadItem].InGroup=FALSE; // do not move the lead item
  1205.    FixVal=item[LeadItem].x;      // set at this value
  1206.  
  1207.    // do the alignment
  1208.    while(TRUE) {
  1209.      if ((CurItem=NextGroupItem())<0) break;    // all items processed
  1210.      DeltaVal=FixVal-item[CurItem].x;           // amount of adjustment
  1211.      MoveEachItem(CurItem,DeltaVal,0);
  1212.    }
  1213.  
  1214.    // find the group item
  1215.    for (i=0;i<TotalItems;i++) if (item[i].type==GROUP) break;
  1216.    if (i<TotalItems) SelItem=i;
  1217.    FrModified=TRUE;
  1218.    FrPaint();                   // refresh the screen
  1219. }
  1220.  
  1221. /******************************************************************************
  1222.    AlignVertRight:
  1223.    Align vertically at the right edge of the selected items.    
  1224. *******************************************************************************/
  1225. void AlignVertRight()
  1226. {
  1227.    int i,LeadItem,DeltaVal,CurItem,FixVal;
  1228.    
  1229.    // exit if a group item not selected
  1230.    if (SelItem<0 || item[SelItem].type!=GROUP) return;
  1231.  
  1232.    StoreUndo();                 // store the undo data
  1233.    
  1234.    MarkGroupItems();            // mark the items in this group
  1235.  
  1236.    // find the lead item as the topmost item
  1237.    if ((LeadItem=TopMostItem())<0) return;
  1238.    item[LeadItem].InGroup=FALSE; // do not move the lead item
  1239.    FixVal=item[LeadItem].x+item[LeadItem].width;// set at this value
  1240.  
  1241.    // do the alignment
  1242.    while(TRUE) {
  1243.      if ((CurItem=NextGroupItem())<0) break;    // all items processed
  1244.      DeltaVal=FixVal-(item[CurItem].x+item[CurItem].width); // amount of adjustment
  1245.      MoveEachItem(CurItem,DeltaVal,0);
  1246.    }
  1247.  
  1248.    // find the group item
  1249.    for (i=0;i<TotalItems;i++) if (item[i].type==GROUP) break;
  1250.    if (i<TotalItems) SelItem=i;
  1251.    FrModified=TRUE;
  1252.    FrPaint();                   // refresh the screen
  1253. }
  1254.  
  1255. /******************************************************************************
  1256.    AlignVertCenter:
  1257.    Align vertically at the vertical center line.
  1258. *******************************************************************************/
  1259. void AlignVertCenter()
  1260. {
  1261.    int i,LeadItem,DeltaVal,CurItem,FixVal;
  1262.    
  1263.    // exit if a group item not selected
  1264.    if (SelItem<0 || item[SelItem].type!=GROUP) return;
  1265.  
  1266.    StoreUndo();                 // store the undo data
  1267.    
  1268.    MarkGroupItems();            // mark the items in this group
  1269.  
  1270.    // find the lead item as the topmost item
  1271.    if ((LeadItem=TopMostItem())<0) return;
  1272.    item[LeadItem].InGroup=FALSE; // do not move the lead item
  1273.    FixVal=item[LeadItem].x+item[LeadItem].width/2;// set at this value
  1274.  
  1275.    // do the alignment
  1276.    while(TRUE) {
  1277.      if ((CurItem=NextGroupItem())<0) break;    // all items processed
  1278.      DeltaVal=FixVal-(item[CurItem].x+item[CurItem].width/2); // amount of adjustment
  1279.      MoveEachItem(CurItem,DeltaVal,0);
  1280.    }
  1281.  
  1282.    // find the group item
  1283.    for (i=0;i<TotalItems;i++) if (item[i].type==GROUP) break;
  1284.    if (i<TotalItems) SelItem=i;
  1285.    FrModified=TRUE;
  1286.    FrPaint();                   // refresh the screen
  1287. }
  1288.  
  1289. /******************************************************************************
  1290.    EvenSpaceHorz:
  1291.    Place the selected items at equal horinzontal distances.
  1292. *******************************************************************************/
  1293. void EvenSpaceHorz()
  1294. {
  1295.    int i,LeadItem,SecondItem,DeltaVal,CurItem,NextPos,distance;
  1296.    
  1297.    // exit if a group item not selected
  1298.    if (SelItem<0 || item[SelItem].type!=GROUP) return;
  1299.  
  1300.    StoreUndo();                 // store the undo data
  1301.    
  1302.    MarkGroupItems();            // mark the items in this group
  1303.  
  1304.    // find the lead and the second items from the left 
  1305.    if ((LeadItem=LeftMostItem())<0) return;      // no more items
  1306.    item[LeadItem].InGroup=FALSE; // remove this item from the list
  1307.    if ((SecondItem=LeftMostItem())<0) return;    // no more items
  1308.  
  1309.    // Calculate the distance
  1310.    distance=item[SecondItem].x-(item[LeadItem].x+item[LeadItem].width);
  1311.    if (distance<0) distance=0;
  1312.    NextPos=item[LeadItem].x+item[LeadItem].width+distance;
  1313.  
  1314.    // Set the position of items starting from the second item
  1315.    while(TRUE) {
  1316.      if ((CurItem=LeftMostItem())<0) break;   // all items processed
  1317.      item[CurItem].InGroup=FALSE;             // remove this item from the list
  1318.      DeltaVal=NextPos-item[CurItem].x;        // amount of adjustment
  1319.      CurItem=MoveEachItem(CurItem,DeltaVal,0);
  1320.      NextPos=item[CurItem].x+item[CurItem].width+distance;
  1321.    }
  1322.  
  1323.    // find the group item
  1324.    for (i=0;i<TotalItems;i++) if (item[i].type==GROUP) break;
  1325.    if (i<TotalItems) SelItem=i;
  1326.    FrModified=TRUE;
  1327.    FrPaint();                   // refresh the screen
  1328. }
  1329.  
  1330. /******************************************************************************
  1331.    EvenSpaceVert:
  1332.    Place the selected items at equal vertical distances.
  1333. *******************************************************************************/
  1334. void EvenSpaceVert()
  1335. {
  1336.    int i,LeadItem,SecondItem,DeltaVal,CurItem,NextPos,distance;
  1337.    
  1338.    // exit if a group item not selected
  1339.    if (SelItem<0 || item[SelItem].type!=GROUP) return;
  1340.  
  1341.    StoreUndo();                 // store the undo data
  1342.    
  1343.    MarkGroupItems();            // mark the items in this group
  1344.  
  1345.    // find the lead and the second items from the left 
  1346.    if ((LeadItem=TopMostItem())<0) return;      // no more items
  1347.    item[LeadItem].InGroup=FALSE; // remove this item from the list
  1348.    if ((SecondItem=TopMostItem())<0) return;    // no more items
  1349.  
  1350.    // Calculate the distance
  1351.    distance=item[SecondItem].y-(item[LeadItem].y+item[LeadItem].height);
  1352.    if (distance<0) distance=0;
  1353.    NextPos=item[LeadItem].y+item[LeadItem].height+distance;
  1354.  
  1355.    // Set the position of items starting from the second item
  1356.    while(TRUE) {
  1357.      if ((CurItem=TopMostItem())<0) break;   // all items processed
  1358.      item[CurItem].InGroup=FALSE;             // remove this item from the list
  1359.      DeltaVal=NextPos-item[CurItem].y;        // amount of adjustment
  1360.      CurItem=MoveEachItem(CurItem,0,DeltaVal);
  1361.      NextPos=item[CurItem].y+item[CurItem].height+distance;
  1362.    }
  1363.  
  1364.    // find the group item
  1365.    for (i=0;i<TotalItems;i++) if (item[i].type==GROUP) break;
  1366.    if (i<TotalItems) SelItem=i;
  1367.    FrModified=TRUE;
  1368.    FrPaint();                   // refresh the screen
  1369. }
  1370.  
  1371. /******************************************************************************
  1372.    EvenSizeHorz:
  1373.    Set the same width (as the first item) for all items in the group
  1374. *******************************************************************************/
  1375. void EvenSizeHorz()
  1376. {
  1377.    int i,LeadItem,width;
  1378.    
  1379.    // exit if a group item not selected
  1380.    if (SelItem<0 || item[SelItem].type!=GROUP) return;
  1381.  
  1382.    StoreUndo();                 // store the undo data
  1383.    
  1384.    MarkGroupItems();            // mark the items in this group
  1385.  
  1386.    // find the lead and the second items from the left 
  1387.    if ((LeadItem=LeftMostItem())<0) return;      // no more items
  1388.    item[LeadItem].InGroup=FALSE; // remove this item from the list
  1389.    width=item[LeadItem].width;   // width of the lead item
  1390.  
  1391.    // Set the width of the remaining items
  1392.    PaintEnabled=FALSE;                          // disable the painting until all items sized
  1393.    while(TRUE) {
  1394.      if ((SelItem=NextGroupItem())<0) break;    // all items processed
  1395.  
  1396.      // Construct the temporary size cursor
  1397.      CursRect.left=item[SelItem].x;
  1398.      CursRect.right=item[SelItem].x+width;      // add the width of the lead item
  1399.      CursRect.top=item[SelItem].y;
  1400.      CursRect.bottom=item[SelItem].y+item[SelItem].height;
  1401.      SizeItem();                                //size this item
  1402.    }
  1403.    PaintEnabled=TRUE;                           //enable painting
  1404.  
  1405.    // find the group item
  1406.    for (i=0;i<TotalItems;i++) if (item[i].type==GROUP) break;
  1407.    if (i<TotalItems) SelItem=i;
  1408.    FrModified=TRUE;
  1409.    FrPaint();                   // refresh the screen
  1410. }
  1411.  
  1412. /******************************************************************************
  1413.    EvenSizeVert:
  1414.    Set the same height (as the first item) for all items in the group
  1415. *******************************************************************************/
  1416. void EvenSizeVert()
  1417. {
  1418.    int i,LeadItem,height;
  1419.    
  1420.    // exit if a group item not selected
  1421.    if (SelItem<0 || item[SelItem].type!=GROUP) return;
  1422.  
  1423.    StoreUndo();                 // store the undo data
  1424.    
  1425.    MarkGroupItems();            // mark the items in this group
  1426.  
  1427.    // find the lead and the second items from the left 
  1428.    if ((LeadItem=LeftMostItem())<0) return;      // no more items
  1429.    item[LeadItem].InGroup=FALSE; // remove this item from the list
  1430.    height=item[LeadItem].height; // height of the lead item
  1431.  
  1432.    // Set the width of the remaining items
  1433.    PaintEnabled=FALSE;                          // disable the painting until all items sized
  1434.    while(TRUE) {
  1435.      if ((SelItem=NextGroupItem())<0) break;    // all items processed
  1436.  
  1437.      // Construct the temporary size cursor
  1438.      CursRect.left=item[SelItem].x;
  1439.      CursRect.right=item[SelItem].x+item[SelItem].width;
  1440.      CursRect.top=item[SelItem].y;
  1441.      CursRect.bottom=item[SelItem].y+height;    // add the height of the lead item
  1442.      SizeItem();                                //size this item
  1443.    }
  1444.    PaintEnabled=TRUE;                           //enable painting
  1445.  
  1446.    // find the group item
  1447.    for (i=0;i<TotalItems;i++) if (item[i].type==GROUP) break;
  1448.    if (i<TotalItems) SelItem=i;
  1449.    FrModified=TRUE;
  1450.    FrPaint();                                   // refresh the screen
  1451. }
  1452.  
  1453. /******************************************************************************
  1454.    ExpandHorizontal:
  1455.    Move all items to the right of the selection rectangle toward right by the 
  1456.    width of the selection rectangle
  1457. *******************************************************************************/
  1458. int ExpandHorizontal()
  1459. {
  1460.    int i,x,y,height,width;
  1461.  
  1462.    // exit if a group item not selected
  1463.    if (SelItem<0 || item[SelItem].type!=GROUP) return TRUE;
  1464.  
  1465.    x=item[SelItem].x;
  1466.    y=item[SelItem].y;
  1467.    width=item[SelItem].width;
  1468.    height=item[SelItem].height;
  1469.  
  1470.    // process each item
  1471.    for (i=0;i<TotalItems;i++) {
  1472.       if (item[i].type==SECTION || item[i].type==GROUP) continue;
  1473.       if (item[i].x<x) continue;                 // do not move items left of the selection rectangle
  1474.       if (item[i].y+item[i].height<y) continue;  // do not move items above the rectangle
  1475.       if (item[i].y>y+height) continue;          // do not move items below the rectangle
  1476.    
  1477.       item[i].x+=width;                          // move item
  1478.    }
  1479.  
  1480.    FrModified=TRUE;
  1481.    FrPaint();
  1482.  
  1483.    return TRUE;
  1484. }
  1485.  
  1486. /******************************************************************************
  1487.    CompressHorizontal:
  1488.    Move all items to the right of the selection rectangle toward left by the 
  1489.    width of the selection rectangle. This function is ignored when an item
  1490.    is found within the rectangle
  1491. *******************************************************************************/
  1492. int CompressHorizontal()
  1493. {
  1494.    int i,x,y,height,width;
  1495.  
  1496.    // exit if a group item not selected
  1497.    if (SelItem<0 || item[SelItem].type!=GROUP) return TRUE;
  1498.  
  1499.    x=item[SelItem].x;
  1500.    y=item[SelItem].y;
  1501.    width=item[SelItem].width;
  1502.    height=item[SelItem].height;
  1503.  
  1504.    // check if an item lies within the selection rectangle
  1505.    for (i=0;i<TotalItems;i++) {
  1506.       if (item[i].type==SECTION || item[i].type==GROUP) continue;
  1507.       if (item[i].y+item[i].height<y) continue;  // do not move items above the rectangle
  1508.       if (item[i].y>y+height) continue;          // do not move items below the rectangle
  1509.       
  1510.       if (item[i].x>=x && item[i].x<=x+width) {
  1511.          MessageBeep(0);
  1512.          return TRUE;
  1513.       }
  1514.    }
  1515.  
  1516.    // process each item
  1517.    for (i=0;i<TotalItems;i++) {
  1518.       if (item[i].type==SECTION || item[i].type==GROUP) continue;
  1519.       if (item[i].x<x) continue;                 // do not move items left of the selection rectangle
  1520.       if (item[i].y+item[i].height<y) continue;  // do not move items above the rectangle
  1521.       if (item[i].y>y+height) continue;          // do not move items below the rectangle
  1522.    
  1523.       item[i].x-=width;                          // move item
  1524.    }
  1525.  
  1526.    FrModified=TRUE;
  1527.    FrPaint();
  1528.  
  1529.    return TRUE;
  1530. }
  1531.  
  1532. /******************************************************************************
  1533.    ExpandVertical:
  1534.    Move all items below the selection rectangle toward bottom by the 
  1535.    height of the selection rectangle
  1536. *******************************************************************************/
  1537. int ExpandVertical()
  1538. {
  1539.    int i,y,height,CurSec;
  1540.  
  1541.    // exit if a group item not selected
  1542.    if (SelItem<0 || item[SelItem].type!=GROUP) return TRUE;
  1543.  
  1544.    y=item[SelItem].y;
  1545.    height=item[SelItem].height;
  1546.    CurSec=item[SelItem].section;
  1547.  
  1548.    // process each item
  1549.    for (i=0;i<TotalItems;i++) {
  1550.       if (item[i].type==GROUP) continue;
  1551.       if (item[i].y<y) continue;                   // do not move items above the rectangle
  1552.    
  1553.       item[i].y+=height;                           // move item
  1554.    }
  1555.  
  1556.    // update the section and form height
  1557.    item[section[CurSec].ScrItem].height+=height;   // expand the current section
  1558.    FrHeight+=height;                               // expand the form
  1559.  
  1560.    FrModified=TRUE;
  1561.    FrPaint();
  1562.  
  1563.    return TRUE;
  1564. }
  1565.  
  1566. /******************************************************************************
  1567.    CompressVertical:
  1568.    Move all items below the selection rectangle upward by the 
  1569.    height of the selection rectangle.  This function is not effective if an
  1570.    item is found within the horizontal band of the selection rectangle
  1571. *******************************************************************************/
  1572. int CompressVertical()
  1573. {
  1574.    int i,y,height,CurSec;
  1575.  
  1576.    // exit if a group item not selected
  1577.    if (SelItem<0 || item[SelItem].type!=GROUP) return TRUE;
  1578.  
  1579.    y=item[SelItem].y;
  1580.    height=item[SelItem].height;
  1581.    CurSec=item[SelItem].section;
  1582.  
  1583.    // check if an item lies in the horizontal band of the selection rectangle
  1584.    for (i=0;i<TotalItems;i++) {
  1585.       if (item[i].type==SECTION || item[i].type==GROUP) continue;
  1586.       if (item[i].y>=y && item[i].y<=y+height) {
  1587.          MessageBeep(0);
  1588.          return TRUE;
  1589.       }
  1590.    }
  1591.  
  1592.    // process each item
  1593.    for (i=0;i<TotalItems;i++) {
  1594.       if (item[i].type==GROUP) continue;
  1595.       if (item[i].y<y) continue;                   // do not move items above the rectangle
  1596.  
  1597.       if (item[i].type==SECTION && item[i].section==CurSec) continue;
  1598.    
  1599.       item[i].y-=height;                           // move item
  1600.    }
  1601.  
  1602.    // update the section and form height
  1603.    item[section[CurSec].ScrItem].height-=height;   // compress the current section
  1604.    FrHeight-=height;                               // compress the form
  1605.  
  1606.    FrModified=TRUE;
  1607.    FrPaint();
  1608.  
  1609.    return TRUE;
  1610. }
  1611.  
  1612.  
  1613. /******************************************************************************
  1614.    StoreUndo:    
  1615.    Store the item data that can be undone later
  1616. *******************************************************************************/
  1617. void StoreUndo()
  1618. {
  1619.    long size;
  1620.  
  1621.    if (UndoItem) DiscardUndo();                 // discard the previous undo
  1622.  
  1623.    // allocate memory for undo
  1624.    if ((size=(long)TotalItems*(long)sizeof(struct StrItem))>32000) return;  // too large
  1625.    if (NULL==(UndoItem=OurAlloc((UINT)size))) return;
  1626.  
  1627.    HugeMove(item,UndoItem,(UINT)size);
  1628.    TotalUndoItems=TotalItems;
  1629. }
  1630.  
  1631. /******************************************************************************
  1632.    DiscardUndo:    
  1633.    Discard the undo data for the previous command.
  1634. *******************************************************************************/
  1635. void DiscardUndo()
  1636. {
  1637.    if (UndoItem) {
  1638.       OurFree(UndoItem);
  1639.       UndoItem=NULL;
  1640.    }
  1641. }
  1642.  
  1643. /******************************************************************************
  1644.    Undo:    
  1645.    Undo the previous arrange command
  1646. *******************************************************************************/
  1647. void Undo()
  1648. {
  1649.    UINT size;
  1650.    int i,CurSec;
  1651.  
  1652.    if (!UndoItem || TotalUndoItems!=TotalItems) {
  1653.       DiscardUndo();
  1654.       return;
  1655.    }
  1656.  
  1657.    // restore previous items
  1658.    size=(UINT)TotalItems*(UINT)sizeof(struct StrItem);
  1659.  
  1660.    HugeMove(UndoItem,item,(UINT)size);
  1661.    DiscardUndo();                             //now discard the undo data
  1662.  
  1663.    // fix the section reference
  1664.    for (i=0;i<TotalItems;i++) {
  1665.       if (item[i].type==SECTION) {
  1666.          CurSec=item[i].section;
  1667.          section[CurSec].ScrItem=i;           //reference to the item number
  1668.       }
  1669.       else if (item[i].type==GROUP) SelItem=i;
  1670.    }
  1671.    FrPaint();                                 // refresh the screen
  1672. }
  1673.  
  1674. /******************************************************************************
  1675.    FrWinUp()    
  1676.    Scroll the window up by one character.
  1677. *******************************************************************************/
  1678. FrWinUp()
  1679. {
  1680.    if (FrWinOrgY>0) {
  1681.       FrWinOrgY-=FrFont[DEFAULT_CFMT].height;
  1682.       PaintFlag=PAINT_WIN;
  1683.       FrPaint();
  1684.    }
  1685.    return TRUE;
  1686. }
  1687.  
  1688. /******************************************************************************
  1689.     FrWinDown:
  1690.    Scroll the window down by one character.
  1691. *******************************************************************************/
  1692. FrWinDown()
  1693. {
  1694.    if (FrWinOrgY<FrHeight) {
  1695.       FrWinOrgY+=FrFont[DEFAULT_CFMT].height;
  1696.       PaintFlag=PAINT_WIN;
  1697.       FrPaint();
  1698.    }
  1699.    return TRUE;
  1700. }
  1701.  
  1702. /******************************************************************************
  1703.    FrWinRight:    
  1704.    Scroll the window right by one character
  1705. *******************************************************************************/
  1706. FrWinRight()
  1707. {
  1708.    if (FrWinOrgX<FrWidth) {
  1709.       FrWinOrgX+=FrFont[DEFAULT_CFMT].height;
  1710.       PaintFlag=PAINT_WIN;
  1711.       FrPaint();
  1712.    }
  1713.    return TRUE;
  1714. }
  1715.  
  1716. /******************************************************************************
  1717.    FrWinLeft:    
  1718.    Scroll the window left by one character
  1719. *******************************************************************************/
  1720. FrWinLeft()
  1721. {
  1722.    if (FrWinOrgX>0) {
  1723.       FrWinOrgX-=FrFont[DEFAULT_CFMT].height;
  1724.       PaintFlag=PAINT_WIN;
  1725.       FrPaint();
  1726.    }
  1727.    return TRUE;
  1728. }
  1729.  
  1730. /******************************************************************************
  1731.     MoveItemArray:
  1732.     Use this routine to insert or delete elements from the item array.
  1733.     Parameters #1 and #2 specify the range of elements to insert or delete.
  1734.     Parameter #3 specifies the request type:
  1735.          'D'  : Delete the array elements
  1736.          'A'  : Insert after the start line element.
  1737.          'B'  : Insert before the start line element.
  1738.     The calling routine must ensure that final item count does not exceed 
  1739.     MaxLines.
  1740.     This routine WILL update the TotalLines variable and will update
  1741.     the 'ScrItem' reference in the section array for the scolled sections.  
  1742. ******************************************************************************/
  1743. void MoveItemArray(int StartItem,int count,char InsertDel) 
  1744. {
  1745.     int  i,CurSec,BeginFix;
  1746.  
  1747.     if (InsertDel=='A') {                     // insert after the start line 
  1748.         if (TotalItems-StartItem-1>0) {    
  1749.            HugeMove(&item[StartItem+1],&item[StartItem+count+1],(TotalItems-StartItem-1)*(long)(sizeof (struct StrItem))); // make space for new item 
  1750.         }
  1751.         TotalItems=TotalItems+count;
  1752.         BeginFix=StartItem+count+1;           // begin the fix at the first scrolled down item
  1753.     }
  1754.     else if (InsertDel=='B') {                // insert before the start line 
  1755.         HugeMove(&item[StartItem],&item[StartItem+count],(TotalItems-StartItem)*(long)(sizeof (struct StrItem))); // make space for new lines 
  1756.         TotalItems=TotalItems+count;
  1757.         BeginFix=StartItem+count;
  1758.     }
  1759.     else {                                    // delete the elements 
  1760.         if (TotalItems-StartItem-count>0) {
  1761.            HugeMove(&item[StartItem+count],&item[StartItem],(TotalItems-StartItem-count)*(long)(sizeof (struct StrItem))); // make space for new lines 
  1762.         }
  1763.         TotalItems=TotalItems-count;
  1764.         BeginFix=StartItem;
  1765.     }
  1766.     
  1767.     // fix the section reference
  1768.     for (i=BeginFix;i<TotalItems;i++) {
  1769.        if (item[i].type==SECTION) {
  1770.           CurSec=item[i].section;
  1771.           section[CurSec].ScrItem=i;           //reference to the item number
  1772.        }
  1773.     }
  1774.  
  1775. }
  1776.  
  1777. /*****************************************************************************
  1778.     CallDialogBox:
  1779.     This function call a modal dialog box, and returns an interger result
  1780. ******************************************************************************/
  1781. int CallDialogBox(LPSTR template,DLGPROC lpProc,DWORD lParam)
  1782. {
  1783.     int result;
  1784.  
  1785.     lpProc = (DLGPROC) MakeProcInstance((FARPROC)lpProc, hFrInst);
  1786.     result=DialogBoxParam(hFrInst,template,hFrWnd,lpProc,lParam);
  1787.     FreeProcInstance((FARPROC)lpProc);      // set back the old window 
  1788.  
  1789.     if (SessionType=='F') {
  1790.        SetFocus(hFrWnd);
  1791.     }
  1792.     return result;
  1793. }
  1794.  
  1795.