/*********************************************************************
* Copyright (C) 2000 by Progress Software Corporation ("PSC"),       *
* 14 Oak Park, Bedford, MA 01730, and other contributors as listed   *
* below.  All Rights Reserved.                                       *
*                                                                    *
* The Initial Developer of the Original Code is PSC.  The Original   *
* Code is Progress IDE code released to open source December 1, 2000.*
*                                                                    *
* The contents of this file are subject to the Possenet Public       *
* License Version 1.0 (the "License"); you may not use this file     *
* except in compliance with the License.  A copy of the License is   *
* available as of the date of this notice at                         *
* http://www.possenet.org/license.html                               *
*                                                                    *
* Software distributed under the License is distributed on an "AS IS"*
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. You*
* should refer to the License for the specific language governing    *
* rights and limitations under the License.                          *
*                                                                    *
* Contributors:                                                      *
*                                                                    *
*********************************************************************/
/*

Procedure:    adetran/pm/_trans.p
Author:       R. Ryan/F. Chang
Purpose:      Translation Manager's Data Tab folder (formerly this
              was called 'Translation' hence the name, hTrans
Background:   This is a persistent procedure that is run from
              pm/_pmain.p *only* after a database is connected.
              Once connected, this procedure has the browser
              and buttons associated with the 'data' functions.

Notes:        A key shared variable, _Language keeps track of what
              the selected language is.  If there are no translations
              available, the language is called (None).  This happens
              when there has not been a consolidation yet.

              Another point, the browser reflects a 3-way join
              among:

                xl_string_info
                xl_instance
                xl_translation (outer-join)

              Because xl_translation is an outer-join, it's values
              appear as '?', or the Progress unknown value.  This
              confuses many users who think that the question mark
              is the translated value (which technically, it could
              be).

Procedures:   key procedures include:

                SetLanguages        Sets the language list-items
                OpenQuery           Opens the query differently depending upon
                                    the contents of _Language
                InsertRow           adds a row - called by insert button
                                    in hMain
                DeleteRow           deletes a row(s) - called by delete
                                    button in hMain
                CreateOrdList       dynamically builds a list of the
                                    columns in the browser that the
                                   'Order Columns' menu-item/button in
                                    hMain uses.
                OrderColumn         Runs the 'Order Columns' dialog.
                Repo                Repositions the cursor at the last
                                    row when a find/goto is made.
                Ref                 Refreshes the browser when a replace
                                    is made in hReplace

Includes:     none

Called by:    pm/_pmmain.p

Calls:        pm/_wizard.w
              pm/_extract.w
              pm/_res.w

Created:      1/95
Updated:      04/99 JEP Added INDEXED-REPOSITION and removed use of BY phrases.
*/



{adetran/pm/vsubset.i &NEW=" " &SHARED="SHARED"}
{ adetran/pm/tranhelp.i }

DEFINE SHARED VARIABLE CurrentTool        AS CHARACTER              NO-UNDO.
DEFINE SHARED VARIABLE _hGloss            AS HANDLE                 NO-UNDO.
DEFINE SHARED VARIABLE _hMain             AS HANDLE                 NO-UNDO.
DEFINE SHARED VARIABLE _hLongStr          AS HANDLE                 NO-UNDO.
DEFINE SHARED VARIABLE _hTrans            AS HANDLE                 NO-UNDO.
DEFINE SHARED VARIABLE _MainWindow        AS HANDLE                 NO-UNDO.
DEFINE SHARED VARIABLE _hSort             AS HANDLE                 NO-UNDO.
DEFINE SHARED VARIABLE _hFind             AS HANDLE                 NO-UNDO.
DEFINE SHARED VARIABLE _Lang              AS CHARACTER              NO-UNDO.
DEFINE SHARED VARIABLE _FullPathFlag      AS LOGICAL                NO-UNDO.
DEFINE SHARED VARIABLE s_Glossary         AS CHARACTER              NO-UNDO.
DEFINE SHARED VARIABLE CurLanguage        AS CHARACTER              NO-UNDO.
DEFINE SHARED VARIABLE tModFlag           AS LOGICAL                NO-UNDO.
DEFINE SHARED VARIABLE pMatchCase         AS LOGICAL                NO-UNDO.
DEFINE SHARED VARIABLE pXREFFileName      AS CHARACTER              NO-UNDO.
DEFINE SHARED VARIABLE pXREFType          AS CHARACTER              NO-UNDO.
DEFINE SHARED VARIABLE pReplaceXREF       AS LOGICAL   INITIAL TRUE NO-UNDO.
DEFINE SHARED VARIABLE pDeleteXREF        AS LOGICAL   INITIAL TRUE NO-UNDO.
DEFINE SHARED VARIABLE OrdMode2           AS CHARACTER              NO-UNDO.
DEFINE SHARED VARIABLE stringROWID        AS ROWID                  NO-UNDO.
DEFINE SHARED VARIABLE instanceROWID      AS ROWID                  NO-UNDO.
DEFINE SHARED VARIABLE translationROWID   AS ROWID                  NO-UNDO.
DEFINE SHARED VARIABLE ProjectDB          AS CHARACTER              NO-UNDO.

/* Temporary files generated by _sort.w and _order.w.                */
/* If these are blank then the regular OpenQuery internal procedures */
/* are run, otherwise these will be run                              */
DEFINE SHARED VARIABLE TmpFl_PM_Tr        AS CHARACTER              NO-UNDO.
DEFINE SHARED VARIABLE TmpFl_PM_Ss        AS CHARACTER              NO-UNDO.
DEFINE        VARIABLE OKPressed          AS LOGICAL                NO-UNDO.
DEFINE        VARIABLE i                  AS INTEGER                NO-UNDO.
DEFINE        VARIABLE init-targ          AS LOGICAL                NO-UNDO.
DEFINE        VARIABLE result             AS LOGICAL                NO-UNDO.
DEFINE        VARIABLE tLog               AS LOGICAL                NO-UNDO.
DEFINE        VARIABLE ThisMessage        AS CHARACTER              NO-UNDO.
DEFINE        VARIABLE ErrorStatus        AS LOGICAL                NO-UNDO.
DEFINE        VARIABLE ColSearchOn        AS LOGICAL                NO-UNDO.
DEFINE        VARIABLE ColSearchHdl       AS HANDLE                 NO-UNDO.
DEFINE        VARIABLE ColSearchType      AS CHARACTER              NO-UNDO.


DEFINE TEMP-TABLE tmp-order
  FIELD OrdCol AS CHARACTER
  FIELD OldNum AS INTEGER
  FIELD NewNum AS INTEGER.

&Scoped-define frame-name  Procsframe
&Scoped-DEFINE BROWSE-name ThisBuffer

DEFINE BUTTON BtnEdit
  LABEL "&Edit"
  SIZE-PIXELS 90 BY 23.

DEFINE BUTTON BtnResources
  LABEL "&Resources..."
  SIZE-PIXELS 90 BY 23.

DEFINE BUTTON BtnExtract
  LABEL "E&xtract..."
  SIZE-PIXELS 90 BY 23.

DEFINE BUTTON BtnFilter
  LABEL "F&ilters..."
  SIZE-PIXELS 90 BY 23.

DEFINE BUTTON BtnLoad
  LABEL "&Load..."
  SIZE-PIXELS 90 BY 23.

DEFINE RECTANGLE rect-1
  EDGE-PIXELS 2 GRAPHIC-EDGE NO-FILL
  SIZE-PIXELS 469 BY 275.

DEFINE VARIABLE LanguageName AS CHARACTER FORMAT "X(256)":U
  VIEW-AS COMBO-BOX INNER-LINES 5 LIST-ITEMS "(None)":U
   SIZE-PIXELS 159 BY 26 NO-UNDO.


/* NOTE that the BUFFERs and QUERY are defined as NEW SHARED
 * because they are defined as SHARED in common/_sort.w
 */
DEFINE NEW SHARED BUFFER ThisString      FOR xlatedb.XL_String_Info.
DEFINE NEW SHARED BUFFER ThisInstance    FOR xlatedb.XL_Instance.
DEFINE NEW SHARED BUFFER ThisTranslation FOR xlatedb.XL_Translation.

DEFINE NEW SHARED QUERY ThisBuffer FOR ThisString, ThisInstance,
                                       ThisTranslation SCROLLING.

DEFINE VARIABLE ThisBufferFileName AS CHARACTER NO-UNDO.
DEFINE BROWSE ThisBuffer QUERY ThisBuffer SHARE-LOCK
  DISPLAY
    ThisString.Original_String COLUMN-LABEL "Source!Phrase"
               WIDTH 20 FORMAT "x(256)":U
    ThisTranslation.trans_string COLUMN-LABEL "Target!Phrase"
               WIDTH 20 FORMAT "x(256)":U
    (IF _FullPathFlag THEN ThisInstance.proc_name ELSE
     SUBSTRING(ThisInstance.proc_name, R-INDEX(ThisInstance.proc_name,"\":U) + 1,
                                               -1,"CHARACTER":U))
@ ThisBufferFileName
        FORMAT "x(256)":U
        WIDTH 30 COLUMN-LABEL "Procedure!Name"
    ThisInstance.Num_Occurs    COLUMN-LABEL "#!Occurs" WIDTH 8 FORMAT "->>,>>9":U
    ThisInstance.Line_Num      COLUMN-LABEL "Line!Number" WIDTH 8 FORMAT ">>,>>9":U
    IF ThisInstance.Justification = 1 THEN "Left":U   ELSE
    IF ThisInstance.Justification = 2 THEN "Right":U  ELSE
    IF ThisInstance.Justification = 3 THEN "Center":U ELSE
    IF ThisInstance.Justification = 4 THEN "Trim":U   ELSE "":U @
      ThisInstance.Justification COLUMN-LABEL "Justifi-!cation" WIDTH 6
    ThisInstance.MaxLength     COLUMN-LABEL "!Length" WIDTH 8 FORMAT ">>9":U
    ThisInstance.ObjectName    COLUMN-LABEL "Object!Name" WIDTH 20
    ThisInstance.Statement     COLUMN-LABEL "!Statement"
    ThisInstance.Item          COLUMN-LABEL "!Item"
    ThisString.Comment         COLUMN-LABEL "!Comments" WIDTH 38 FORMAT "X(80)":U
    ThisInstance.proc_name     WIDTH 40 FORMAT "x(256)" COLUMN-LABEL "Path'ed Procedure!Name"
  ENABLE
    ThisString.Original_String
    ThisTranslation.trans_string
    ThisString.Comment
    ThisInstance.proc_name
  WITH SEPARATORS MULTIPLE SIZE-PIXELS 442 BY 212 FONT 4.

DEFINE FRAME Procsframe
  LanguageName AT Y 21  X 13  COLON-ALIGNED NO-LABEL
  BtnExtract   AT Y 8   X 498
  BtnFilter    AT Y 35  X 498
  BtnLoad      AT Y 62  X 498
  ThisBuffer   AT Y 57  X 25
  BtnResources AT Y 89  X 498
  BtnEdit      AT Y 116 X 498
  rect-1       AT Y 8   X 12
  WITH 1 DOWN NO-BOX OVERLAY SIDE-LABELS NO-UNDERLINE THREE-D
  AT X 14 Y 52 SIZE-PIXELS 602 BY 299 FONT 4.


/* Triggers */
ON HELP OF FRAME Procsframe DO:
  RUN adecomm/_adehelp.p ("tran":U,"context":U,{&data_tab_folder}, ?).
END.

ON CHOOSE OF BtnFilter IN FRAME ProcsFrame DO:
  RUN adecomm/_setcurs.p ("WAIT":U).
  RUN adetran/pm/_wizard.w.
END.

ON CHOOSE OF BtnEdit IN FRAME Procsframe DO:
  DEFINE VARIABLE pFileName AS CHARACTER        NO-UNDO.
  DEFINE VARIABLE DirName   AS CHARACTER        NO-UNDO.

  IF ThisBuffer:NUM-SELECTED-ROWS = 0 THEN DO:
    ThisMessage = "You haven't selected a procedure to edit.".
    RUN adecomm/_s-alert.p (input-output ErrorStatus, "w":U,"ok":U, ThisMessage).
    RETURN.
  END.

  /* Get Source Code directory. */
  IF NOT AVAILABLE xlatedb.xl_project THEN
    FIND FIRST xlatedb.xl_project NO-LOCK NO-ERROR.

  /* Construct the full pathname using SourceDir, Instance Filename
     (inst. filename contains the files relative path as well).
  */
  RUN adecomm/_osfmush.p
      (INPUT  xlatedb.xl_project.ApplDirectory,
       INPUT  ThisInstance.proc_name,
       OUTPUT pFileName ).

  FILE-INFO:FILENAME = pFileName.
  IF FILE-INFO:FULL-PATHNAME = ? THEN DO:
    ThisMessage = pFileName + "^This file cannot be found.".
    RUN adecomm/_s-alert.p (INPUT-OUTPUT ErrorStatus, "w":U,"ok":U, ThisMessage).
  END.
  ELSE RUN adecomm/_pwmain.p ("_tran.p":U, pFileName,"").
END.

ON CHOOSE OF BtnResources IN FRAME ProcsFrame DO:
  DEFINE VARIABLE SettingsFile AS CHARACTER       NO-UNDO.
  DEFINE VARIABLE ErrorStatus  AS LOGICAL         NO-UNDO.

  RUN adecomm/_setcurs.p ("WAIT":U).
  RUN adetran/pm/_res.w (OUTPUT SettingsFile, OUTPUT OKPressed, OUTPUT ErrorStatus).
END.

ON CHOOSE OF BtnExtract IN FRAME Procsframe DO:
  RUN adecomm/_setcurs.p ("WAIT":U).
  RUN disable_menu_bar IN _hMain.
  RUN adetran/pm/_extract.w (
    OUTPUT OKpressed,
    INPUT-OUTPUT pXREFFileName,
    INPUT-OUTPUT pXREFType,
    INPUT-OUTPUT pDeleteXREF).
  RUN enable_menu_bar IN _hMain.
END.

ON CHOOSE OF BtnLoad IN FRAME Procsframe DO:
  RUN adecomm/_setcurs.p ("WAIT":U).
  RUN disable_menu_bar IN _hMain.
  RUN adetran/pm/_loadstr.w (
    OUTPUT OKpressed,
    INPUT-OUTPUT pXREFFileName,
    INPUT-OUTPUT pXREFType,
    INPUT-OUTPUT pDeleteXREF).
  IF OKPressed THEN DO:
    FIND FIRST xlatedb.XL_Project EXCLUSIVE-LOCK NO-ERROR.
    IF AVAILABLE xlatedb.XL_Project THEN
      ASSIGN xlatedb.XL_Project.ProjectRevision =
         ENTRY(1, xlatedb.XL_Project.ProjectRevision, CHR(4)) +
               CHR(4) + "No":U + CHR(4) +
         (IF NUM-ENTRIES(xlatedb.XL_Project.ProjectRevision,CHR(4)) > 2 THEN
            ENTRY(3, xlatedb.XL_Project.ProjectRevision, CHR(4)) ELSE "NO":U).
  END. /* If OKPressed */
  RUN enable_menu_bar IN _hMain.
END.

ON ANY-KEY OF ThisString.Original_String IN BROWSE ThisBuffer DO:
  IF NOT CAN-DO(
     "CURSOR-RIGHT,CURSOR-LEFT,CURSOR-DOWN,CURSOR-UP,END,HOME,TAB",
     KEYLABEL(LASTKEY)) THEN RETURN NO-APPLY.
END.
ON ANY-KEY OF ThisInstance.proc_name IN BROWSE ThisBuffer DO:
  IF NOT CAN-DO(
     "CURSOR-RIGHT,CURSOR-LEFT,CURSOR-DOWN,CURSOR-UP,END,HOME,TAB",
     KEYLABEL(LASTKEY)) THEN RETURN NO-APPLY.
END.

ON ENTRY OF ThisBuffer DO:
   RUN CustSensi IN _hMain(ThisBuffer:HANDLE IN FRAME {&FRAME-NAME}).
END.

ON VALUE-CHANGED OF ThisBuffer OR ROW-LEAVE OF ThisBuffer DO:
  BtnEdit:SENSITIVE = ThisBuffer:NUM-SELECTED-ROWS >=1.
  FIND FIRST xlatedb.XL_Project EXCLUSIVE-LOCK NO-ERROR.
  IF AVAILABLE xlatedb.XL_Project THEN
    ASSIGN xlatedb.XL_Project.ProjectRevision =
       ENTRY(1, xlatedb.XL_Project.ProjectRevision, CHR(4)) +
             CHR(4) + "No":U + CHR(4) +
       (IF NUM-ENTRIES(xlatedb.XL_Project.ProjectRevision,CHR(4)) > 2 THEN
         ENTRY(3, xlatedb.XL_Project.ProjectRevision, CHR(4)) ELSE "NO":U).
  IF NOT AVAILABLE ThisTranslation THEN
  RUN Refresh IN _hLongStr (INPUT ThisString.Original_String,
                            INPUT "":U,
                            INPUT _hTrans).
  ELSE
  RUN Refresh IN _hLongStr (INPUT ThisString.Original_String,
                            INPUT ThisTranslation.Trans_String,
                            INPUT _hTrans).
  ASSIGN
     stringROWID      = IF AVAILABLE ThisString
                           THEN ROWID(ThisString)       ELSE ?
     instanceROWID    = IF AVAILABLE ThisInstance
                           THEN ROWID(ThisInstance)     ELSE ?
     translationROWID = IF AVAILABLE ThisTranslation
                           THEN ROWID(ThisTranslation)  ELSE ?
  .
END.

ON VALUE-CHANGED OF LanguageName DO:
  ASSIGN _Lang = LanguageName:SCREEN-VALUE IN FRAME {&FRAME-NAME}.
  run OpenQuery.
  /* Set s_glossary according to new language name */
  FIND FIRST xlatedb.XL_Glossary WHERE xlatedb.XL_Glossary.GlossaryType MATCHES
           "*":U + LanguageName:SCREEN-VALUE NO-LOCK NO-ERROR.
  IF AVAILABLE xlatedb.XL_Glossary THEN s_Glossary = xlatedb.XL_Glossary.GlossaryName.
END.

ON LEAVE OF ThisTranslation.trans_string IN BROWSE ThisBuffer DO:
  /* If this is not a brand new translation */
  IF NOT init-targ AND
    ThisTranslation.Trans_String:SCREEN-VALUE IN BROWSE ThisBuffer = "":U THEN
  DO TRANSACTION:
    IF AVAILABLE ThisTranslation THEN
    DO:
       ASSIGN ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = FALSE.
       ASSIGN
          stringROWID = ROWID(ThisString)
          instanceROWID = ROWID(ThisInstance)
          translationROWID = ?.
       DELETE ThisTranslation.
       result = ThisBuffer:DELETE-RESULT-LIST-ENTRY().
       FIND ThisString WHERE ROWID(ThisString) = stringROWID.
       FIND ThisInstance WHERE ROWID(ThisInstance) = instanceROWID.
       result = ThisBuffer:CREATE-RESULT-LIST-ENTRY().
       ASSIGN ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = TRUE.
    END. /* Remove the Result Set with the old ThisTranlation, recreate with ? */
    ELSE ThisTranslation.Trans_String = ?.
  END.
  ELSE DO:
    RUN updateGloss.
  END. /* Else DO */
END.

ON ENTRY OF ThisTranslation.trans_string IN BROWSE ThisBuffer DO:
  DEFINE VARIABLE rid       AS INTEGER   NO-UNDO.

  init-targ = YES.

  IF NOT AVAILABLE (ThisTranslation) THEN DO:
    ASSIGN
       init-targ        = NO
       stringROWID      = ROWID(ThisString)
       instanceROWID    = ROWID(ThisInstance)
       translationROWID = ?
    .

    ASSIGN ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = FALSE.
    GET CURRENT ThisBuffer NO-LOCK.
    ASSIGN
      rid  = CURRENT-RESULT-ROW("ThisBuffer":U)
      tlog = ThisBuffer:SET-REPOSITIONED-ROW(MAX(1,ThisBuffer:FOCUSED-ROW), "CONDITIONAL")
               IN FRAME ProcsFrame.

    /* Since the join in this browser may include strings which have no translation
     * record, this routine creates a new translation record, reopens the query, and
     * repositions the user back to the record. (GFS)
     */
    CREATE ThisTranslation.
    ASSIGN
      ThisTranslation.Sequence_Num = ThisInstance.Sequence_Num
      ThisTranslation.Instance_Num = ThisInstance.Instance_Num
      ThisTranslation.Lang_Name    = (IF LanguageName:SCREEN-VALUE IN FRAME ProcsFrame NE "" THEN
                                         LanguageName:SCREEN-VALUE IN FRAME ProcsFrame
                                      ELSE "")
      ThisTranslation.Trans_String = ""
      ThisTranslation.Last_Change  = INT(TODAY) + (TIME / 100000)
      translationROWID = ROWID(ThisTranslation).

    result = ThisBuffer:DELETE-RESULT-LIST-ENTRY().
    FIND ThisString WHERE ROWID(ThisString) = stringROWID.
    FIND ThisInstance WHERE ROWID(ThisInstance) = instanceROWID.
    FIND ThisTranslation WHERE ROWID(ThisTranslation) = translationROWID.
    result = ThisBuffer:CREATE-RESULT-LIST-ENTRY().

    ASSIGN ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = TRUE.
    RUN Repo (stringROWID, instanceROWID, translationROWID, ?).

    /* Refresh browse to avoid problem with screen-value in 9.1D*/
    ThisBuffer:REFRESH().

  END. /* No Translation is available */
  ELSE IF ThisTranslation.Trans_String = ? THEN init-targ = NO.
END.

ON MOUSE-SELECT-DBLCLICK OF BROWSE ThisBuffer, ThisString.Original_String,
  ThisTranslation.Trans_string DO:
  IF NOT CAN-FIND(FIRST xlatedb.XL_Glossary) THEN RETURN NO-APPLY.
  IF NOT AVAILABLE ThisTranslation THEN
  RUN Realize IN _hLongStr (INPUT ThisString.Original_String,
                            INPUT "":U,
                            INPUT _hTrans).
  ELSE
  RUN Realize IN _hLongStr (INPUT ThisString.Original_String,
                            INPUT ThisTranslation.Trans_String,
                            INPUT _hTrans).
END.

ON START-SEARCH OF ThisBuffer IN FRAME Procsframe
DO:
  ColSearchOn = Yes.
  ColSearchHdl = ThisBuffer:CURRENT-COLUMN.
  CASE ColSearchHdl:LABEL:
    WHEN "Source!Phrase":u OR WHEN "Target!Phrase":u THEN
    DO:
       ColSearchType = SUBSTRING(ColSearchHdl:LABEL, 1, 1, "CHARACTER":U).
    END.

    OTHERWISE
    DO:
      ColSearchType = "":u.
      IF NOT CAN-DO("ThisBufferFileName,ObjectName,Statement,Item,Comment,Proc_Name":u , ColSearchHdl:NAME) THEN
      DO:
        ColSearchOn = No.
        APPLY "END-SEARCH":u TO BROWSE ThisBuffer.
      END.
    END.
  END CASE.
END.

ON END-SEARCH OF ThisBuffer IN FRAME Procsframe
DO:
  ColSearchOn = No.
  ColSearchType = "":u.
END.

ON ANY-PRINTABLE OF ThisBuffer IN FRAME Procsframe
DO:
  DEFINE VARIABLE proc-name AS CHARACTER NO-UNDO.
  DEFINE VARIABLE found-one AS LOGICAL   NO-UNDO.

  IF NOT ColSearchOn OR NOT VALID-HANDLE(_hFind) THEN RETURN.

  /* Perform special column searching. */
  IF ColSearchType <> "":u THEN
  DO:
    RUN SetColSearch IN _hFind (INPUT ColSearchType, INPUT LAST-EVENT:LABEL).
    RUN FindNextTran.ip IN _hFind.
  END.
  ELSE
  DO:
    RUN adecomm/_setcurs.p ("WAIT":U).
    col-search-blk:
    DO WHILE TRUE:
      GET NEXT ThisBuffer.
      IF QUERY-OFF-END("ThisBuffer":u) THEN
      DO:
        /* Go back to most recent current column. */
        IF stringROWID <> ? THEN
          RUN Repo (stringROWID, instanceROWID, translationROWID,?).
        LEAVE col-search-blk.
      END.
      IF ColSearchHdl:NAME = "ThisBufferFileName":u THEN
      DO:
        proc-name = (IF _FullPathFlag THEN ThisInstance.proc_name ELSE
                     SUBSTRING(ThisInstance.proc_name, R-INDEX(ThisInstance.proc_name,"\":U) + 1,
                                                 -1,"CHARACTER":U)).
        found-one = (proc-name BEGINS LAST-EVENT:LABEL).
      END.
      ELSE IF ColSearchHdl:NAME = "ObjectName":u THEN
        found-one = (ThisInstance.ObjectName BEGINS LAST-EVENT:LABEL).
      ELSE IF ColSearchHdl:NAME = "Statement":u THEN
        found-one = (ThisInstance.Statement BEGINS LAST-EVENT:LABEL).
      ELSE IF ColSearchHdl:NAME = "Item":u THEN
        found-one = (ThisInstance.Item BEGINS LAST-EVENT:LABEL).
      ELSE IF ColSearchHdl:NAME = "Comment":u THEN
        found-one = (ThisString.Comment BEGINS LAST-EVENT:LABEL).
      ELSE IF ColSearchHdl:NAME = "Proc_Name":u THEN
        found-one = (ThisInstance.Proc_Name BEGINS LAST-EVENT:LABEL).

      IF found-one THEN
      DO:
        ASSIGN
           stringROWID      = IF AVAILABLE ThisString
                                 THEN ROWID(ThisString)       ELSE ?
           instanceROWID    = IF AVAILABLE ThisInstance
                                 THEN ROWID(ThisInstance)     ELSE ?
           translationROWID = IF AVAILABLE ThisTranslation
                                 THEN ROWID(ThisTranslation)  ELSE ? .
        RUN Repo (stringROWID, instanceROWID, translationROWID,?).
        LEAVE col-search-blk.
      END.  /* IF found-one */
    END. /* DO WHILE TRUE - col-search-blk */
    RUN adecomm/_setcurs.p ("":U).
  END.

END.

/*  Main code block */
&SCOPED-DEFINE FRAME-NAME ProcsFrame
{adetran/common/noscroll.i}
PAUSE 0 BEFORE-HIDE.

MAIN-BLOCK:
DO ON ERROR   UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK
   ON END-KEY UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK:
  ASSIGN FRAME {&FRAME-NAME}:PARENT      = _MainWindow
         ThisBuffer:NUM-LOCKED-COLUMNS   = 1.

END.
{adecomm/_adetool.i}


/* procedures */
PROCEDURE Goto:
    /* Repositions Data Tab browse to the top or bottom row. */
    DEFINE INPUT PARAMETER gotoFlag         AS CHARACTER NO-UNDO.

    IF NOT BROWSE ThisBuffer:SENSITIVE THEN RETURN.

    CASE gotoFlag:
      WHEN 'TOP':u THEN
        APPLY 'HOME':u TO BROWSE ThisBuffer.

      WHEN 'BOTTOM':u THEN
        APPLY 'END':u TO BROWSE ThisBuffer.
    END CASE.

END PROCEDURE.


PROCEDURE HideMe :
  _lang = LanguageName:SCREEN-VALUE IN FRAME {&FRAME-NAME}.
  frame {&FRAME-NAME}:HIDDEN = true.
END PROCEDURE.


PROCEDURE SetLanguages:
  DO WITH FRAME {&FRAME-NAME}:
    LanguageName = "".
    FOR EACH xlatedb.XL_Language NO-LOCK:
      LanguageName = if LanguageName = "" THEN xlatedb.XL_Language.Lang_Name
                     else LanguageName + ",":U + xlatedb.XL_Language.Lang_Name.
    END.

    IF LanguageName = "" THEN LanguageName = "(None)":U.
    ASSIGN
      LanguageName:list-items   = LanguageName
      LanguageName:SCREEN-VALUE = if _Lang <> "" AND
                                    LOOKUP(_lang,LanguageName) > 0
                                  THEN _Lang
                                  ELSE LanguageName:ENTRY(1)
      LanguageName:SENSITIVE    = LanguageName:SCREEN-VALUE <> "(None)":U.
  END.
END PROCEDURE.


PROCEDURE OpenQuery :
  DO WITH FRAME {&FRAME-NAME}:

    DEFINE VARIABLE MaxGuess AS INTEGER INITIAL 100         NO-UNDO.
    RUN adecomm/_setcurs.p ("WAIT":U).

    FIND FIRST xlatedb.XL_Project.
    IF AVAILABLE xlatedb.XL_Project THEN
      MaxGuess = xlatedb.XL_Project.NumberOfPhrases.

    IF TmpFl_PM_Tr NE "" THEN RUN VALUE(TmpFl_PM_Tr).

    ELSE IF LanguageName:SCREEN-VALUE = "(None)":U THEN DO:
      OPEN QUERY ThisBuffer
      FOR EACH ThisString USE-INDEX String_Key, /* BY ThisString.KeyOfString */
        EACH ThisInstance WHERE ThisInstance.Sequence_num = ThisString.Sequence_num
                          USE-INDEX SequenceInst,
        EACH ThisTranslation WHERE ThisTranslation.Sequence_num = ThisInstance.Sequence_num
                               AND ThisTranslation.Instance_num = ThisInstance.Instance_num
                             USE-INDEX seq_inst
                             OUTER-JOIN SHARE-LOCK INDEXED-REPOSITION.
    END.

    ELSE DO:
      OPEN QUERY ThisBuffer
      FOR EACH ThisString USE-INDEX String_Key, /* BY ThisString.KeyOfString */
        EACH ThisInstance WHERE ThisInstance.Sequence_num = ThisString.Sequence_num
                          USE-INDEX SequenceInst,
        EACH ThisTranslation WHERE ThisTranslation.Sequence_num = ThisInstance.Sequence_num
                               AND ThisTranslation.Instance_num = ThisInstance.Instance_num
                               AND ThisTranslation.lang_name = LanguageName:SCREEN-VALUE
                             USE-INDEX seq_inst
                             OUTER-JOIN SHARE-LOCK INDEXED-REPOSITION.
      ASSIGN
         StringROWID      = IF AVAILABLE ThisString THEN
                               ROWID(ThisString) ELSE ?.
         InstanceROWID    = IF AVAILABLE ThisInstance THEN
                               ROWID(ThisInstance) ELSE ?.
         TranslationROWID = IF AVAILABLE ThisTranslation THEN
                               ROWID(ThisTranslation) ELSE ?.
    END.

    IF MaxGuess > 0  THEN ThisBuffer:MAX-DATA-GUESS = MaxGuess.
    IF OrdMode2 = "" THEN RUN CreateOrdList.
    RUN adecomm/_setcurs.p ("").

  END.
END PROCEDURE.


PROCEDURE Realize:
  DO WITH FRAME {&FRAME-NAME}:
    FRAME {&FRAME-NAME}:HIDDEN = TRUE.

    /* Use the enable statement to set up the correct tab order */
    ENABLE
      ThisBuffer
      BtnFilter
      BtnExtract
      BtnLoad
      BtnEdit
    WITH FRAME {&FRAME-NAME}.

    /* Set the screen value of LanguageName */
    IF s_glossary NE "":U AND s_glossary NE ? THEN DO:
      FIND xlatedb.XL_Glossary WHERE xlatedb.XL_Glossary.GlossaryName = s_glossary
           NO-LOCK NO-ERROR.
      IF AVAILABLE xlatedb.XL_Glossary AND
         NUM-ENTRIES(xlatedb.XL_Glossary.GlossaryType,"/":U) > 1
      THEN DO:
        FIND xlatedb.XL_Language WHERE xlatedb.XL_Language.Lang_Name =
             ENTRY(2, xlatedb.XL_Glossary.GlossaryType,"/":U) NO-LOCK NO-ERROR.
        IF AVAILABLE xlatedb.XL_Language THEN DO:
          LanguageName:SCREEN-VALUE = xlatedb.XL_Language.Lang_Name NO-ERROR.
          APPLY "VALUE-CHANGED":U TO languageName.
        END.
      END.
    END.
    /* now sensitize the buttons depending upon whether or not there are any procedures. */
    RUN SetLanguages.
    FIND FIRST xlatedb.XL_Project NO-LOCK NO-ERROR.
    IF AVAILABLE xlatedb.XL_Project AND xlatedb.XL_Project.Numberofprocedures >= 1 THEN
    ASSIGN
       LanguageName:SENSITIVE = LanguageName:SCREEN-VALUE <> "(None)":U
       ThisBuffer:SENSITIVE   = true
       BtnExtract:SENSITIVE   = true
       BtnFilter:SENSITIVE    = true
       BtnLoad:SENSITIVE      = true
       BtnResources:SENSITIVE = true
       ThisTranslation.trans_string:READ-ONLY IN BROWSE ThisBuffer =
                                NOT LanguageName:SENSITIVE.
    ELSE DO:
      ASSIGN
       LanguageName:SENSITIVE = false
       ThisBuffer:SENSITIVE   = false
       BtnExtract:SENSITIVE   = false
       BtnFilter:SENSITIVE    = false
       BtnLoad:SENSITIVE      = false
       BtnResources:SENSITIVE = false.
    END.

    APPLY "VALUE-CHANGED":U TO LanguageName.

    ASSIGN
      BtnEdit:SENSITIVE          = ThisBuffer:NUM-SELECTED-ROWS >= 1
      FRAME {&FRAME-NAME}:HIDDEN = FALSE.

    APPLY "ENTRY":U TO FRAME {&FRAME-NAME}.
  END.
END PROCEDURE.

PROCEDURE Repo:
   /* Expanded to deal with SkyWalker's enhancement to REPOSITION */
   DEFINE INPUT PARAMETER stringROWID      AS ROWID       NO-UNDO.
   DEFINE INPUT PARAMETER instanceROWID    AS ROWID       NO-UNDO.
   DEFINE INPUT PARAMETER translationROWID AS ROWID       NO-UNDO.
   DEFINE INPUT PARAMETER pRow             AS INTEGER     NO-UNDO.

   ASSIGN ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = FALSE.
   IF stringROWID = ? AND (pRow = ? OR pRow = 0) THEN .
   ELSE IF stringROWID = ? THEN
      REPOSITION ThisBuffer TO ROW pRow. /* NO-ERROR */
   ELSE DO:
      tlog = ThisBuffer:SET-REPOSITIONED-ROW(INTEGER(ThisBuffer:num-iterations / 2),
                                             "CONDITIONAL":U) IN FRAME {&FRAME-NAME}.

      REPOSITION ThisBuffer TO ROWID stringROWID, instanceROWID, translationROWID NO-ERROR.

   END. /* Valid ROWIDs */
   ASSIGN ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = TRUE.
   IF NOT ERROR-STATUS:ERROR THEN tlog = ThisBuffer:SELECT-FOCUSED-ROW().
END PROCEDURE.


PROCEDURE OrderColumn:
   {adetran/common/_order.i ThisBuffer}
END.

PROCEDURE SortQuery:
  DEFINE INPUT PARAMETER pTempFile AS CHARACTER                NO-UNDO.

  IF pTempFile NE TmpFl_PM_Tr THEN DO:
    IF TmpFl_PM_Tr NE "" THEN OS-DELETE VALUE(TmpFl_PM_Tr).
    TmpFl_PM_Tr = pTempFile.
  END.

  IF VALID-HANDLE(_hSort) THEN DELETE PROCEDURE _hSort.
  RUN VALUE(pTempFile) PERSISTENT SET _hSort.
  IF VALID-HANDLE(_hSort) THEN _hSort:PRIVATE-DATA = CurrentTool.
  FIND FIRST xlatedb.XL_Project NO-ERROR.
  IF AVAILABLE xlatedb.XL_Project AND xlatedb.XL_Project.NumberOfPhrases > 0 THEN
    ThisBuffer:MAX-DATA-GUESS IN FRAME {&FRAME-NAME} = xlatedb.XL_Project.NumberOfPhrases.
END.

PROCEDURE DeleteRow:
  DEFINE VARIABLE num-sel-rows         AS INTEGER                        NO-UNDO.

  num-sel-rows = ThisBuffer:NUM-SELECTED-ROWS IN FRAME {&FRAME-NAME}.
  IF num-sel-rows < 1 THEN DO:
    ThisMessage = "You must select a row first.".
    RUN adecomm/_s-alert.p (INPUT-OUTPUT ErrorStatus, "w":U,"ok":U, ThisMessage).
    RETURN.
  END.

  MESSAGE "Delete selected rows?" VIEW-AS ALERT-BOX QUESTION BUTTONS yes-no
          TITLE "Delete Verification" UPDATE result.
  IF NOT result THEN RETURN.

  DO WITH FRAME {&FRAME-NAME}:
    tModFlag = TRUE.
    RUN adecomm/_setcurs.p ("WAIT":U).
    ASSIGN ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = FALSE.
    DO i = 1 TO num-sel-rows:
      IF i = 1 THEN
      DO:
         /* Get the PREV record in order to REPOSITION to it, instead of REPOSITION
          * to the FIRST record */
         result = ThisBuffer:fetch-selected-row(i).
         tlog = ThisBuffer:SET-REPOSITIONED-ROW(MAX(1,ThisBuffer:FOCUSED-ROW - 1), "CONDITIONAL":U) IN FRAME ProcsFrame.
         GET PREV ThisBuffer.
         ASSIGN
            stringROWID = ROWID(ThisString)
            instanceROWID = ROWID(ThisInstance)
            translationROWID = IF AVAILABLE ThisTranslation
                               THEN ROWID(ThisTranslation) ELSE ?.
      END. /* i = 1 */
      /* NOTE that there is a database trigger for DELETE ThisInstance
       * that will automatically delete the related translations
       * and related string_info if this is the last instance with that
       * string_info (pm/_trgpdin.p)
       */
      result = ThisBuffer:FETCH-SELECTED-ROW(i).
      DELETE ThisInstance.
    END. /* i= 1 to num-sel-rows */
    result = ThisBuffer:DELETE-SELECTED-ROWS().
    ASSIGN ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = TRUE.
    RUN Repo (stringROWID, instanceROWID, translationROWID,?).
  END.

  FIND FIRST xlatedb.XL_Project EXCLUSIVE-LOCK NO-ERROR.
  IF AVAILABLE xlatedb.XL_Project THEN
    ASSIGN xlatedb.XL_Project.ProjectRevision =
              ENTRY(1, xlatedb.XL_Project.ProjectRevision, CHR(4)) +
                    CHR(4) + "No":U + CHR(4) +
       (IF NUM-ENTRIES(xlatedb.XL_Project.ProjectRevision,CHR(4)) > 2 THEN
         ENTRY(3, xlatedb.XL_Project.ProjectRevision, CHR(4)) ELSE "NO":U).

  RUN SetSensitivity IN _hMain.
  RUN adecomm/_setcurs.p ("").
END PROCEDURE.  /* Delete Row */

PROCEDURE DeleteTarget:
/* Note that we are running OpenQuery, because the DELETE-RESULT-LIST-ENTRY
 * does not work with multiple browse chosen
 */
DEFINE VARIABLE num-sel-rows         AS INTEGER                NO-UNDO.
DEFINE VARIABLE delTarg              AS LOGICAL INITIAL NO     NO-UNDO.

  num-sel-rows = ThisBuffer:NUM-SELECTED-ROWS IN FRAME {&FRAME-NAME}.
  IF num-sel-rows < 1 THEN DO:
    ThisMessage = "You must select a row first.".
    RUN adecomm/_s-alert.p (INPUT-OUTPUT ErrorStatus, "w":U,"ok":U, ThisMessage).
    RETURN.
  END.

  MESSAGE "Delete selected target phrases?" VIEW-AS ALERT-BOX QUESTION BUTTONS yes-no
          TITLE "Delete Verification" UPDATE result.
  IF NOT result THEN RETURN.

  DO WITH FRAME {&FRAME-NAME}:
    tModFlag = TRUE.
    RUN adecomm/_setcurs.p ("WAIT":U).
    ASSIGN ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = FALSE.

    DO i = 1 TO num-sel-rows:
      result = ThisBuffer:FETCH-SELECTED-ROW(i).
      IF i = 1 THEN
      ASSIGN
         stringROWID = ROWID(ThisString)
         instanceROWID = ROWID(ThisInstance)
         translationROWID = IF AVAILABLE ThisTranslation THEN
                               ROWID(ThisTranslation) ELSE ?.
      result = ThisBuffer:FETCH-SELECTED-ROW(i).
      IF AVAILABLE ThisTranslation THEN
      DO:
         DELETE ThisTranslation.
         delTarg = YES.
      END.
    END. /* i= 1 to num-sel-rows */
    ASSIGN ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = TRUE.
  END.

  IF delTarg THEN
  DO:
     RUN OpenQuery.
     FIND FIRST xlatedb.XL_Project EXCLUSIVE-LOCK NO-ERROR.
     IF AVAILABLE xlatedb.XL_Project THEN
        ASSIGN xlatedb.XL_Project.ProjectRevision =
              ENTRY(1, xlatedb.XL_Project.ProjectRevision, CHR(4)) +
                    CHR(4) + "No":U + CHR(4) +
       (IF NUM-ENTRIES(xlatedb.XL_Project.ProjectRevision,CHR(4)) > 2 THEN
         ENTRY(3, xlatedb.XL_Project.ProjectRevision, CHR(4)) ELSE "NO":U).
  END.

  RUN SetSensitivity IN _hMain.
  RUN adecomm/_setcurs.p ("").
END PROCEDURE.  /* Delete Target */

PROCEDURE InsertRow:
END PROCEDURE.


PROCEDURE EnableFrame :
  DEFINE INPUT PARAMETER pMode AS LOGICAL               NO-UNDO.
  FRAME {&FRAME-NAME}:SENSITIVE = pMode.
END PROCEDURE.


PROCEDURE CreateOrdList :
  DO WITH FRAME {&FRAME-NAME}:
     DEFINE VARIABLE tBrColWH     AS WIDGET-HANDLE        NO-UNDO.
     DEFINE VARIABLE tListItems   AS CHARACTER            NO-UNDO.

     ASSIGN tBrColWH   = ThisBuffer:FIRST-COLUMN
            tListItems = "".

     DO WHILE tBrColWH <> ?:
       ASSIGN tListItems = tListItems + ",":U +  tBrColWh:LABEL
              tBrColWH   = tBrColWH:NEXT-COLUMN.
     END.

     ASSIGN tListItems = TRIM(tListItems,",":U)
            tListItems = REPLACE(tListItems,"!","")
            OrdMode2 = tListItems.
  END.  /* Do with {&FRAME-NAME} */
END PROCEDURE.


PROCEDURE Store-Long-String:
  DEFINE INPUT PARAMETER src       AS CHARACTER               NO-UNDO.
  DEFINE INPUT PARAMETER trg       AS CHARACTER               NO-UNDO.
  DEFINE VARIABLE rid              AS INTEGER                 NO-UNDO.

  /* First make sure that we are still on the correct row of the browse  */
  IF ThisString.Original_String NE src THEN RETURN.
  IF trg = ? THEN RETURN.

  ASSIGN
     stringROWID      = ROWID(ThisString)
     instanceROWID    = ROWID(ThisInstance)
     translationROWID = ?.
  .
  IF NOT AVAILABLE (ThisTranslation) THEN DO:
     ASSIGN
        ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = FALSE.
     GET CURRENT ThisBuffer NO-LOCK.
     ASSIGN
        rid  = CURRENT-RESULT-ROW("ThisBuffer":U)
        tlog = ThisBuffer:SET-REPOSITIONED-ROW(MAX(1,ThisBuffer:FOCUSED-ROW), "CONDITIONAL")
                 IN FRAME ProcsFrame.
    CREATE ThisTranslation.
    ASSIGN
      ThisTranslation.Sequence_Num = ThisInstance.Sequence_Num
      ThisTranslation.Instance_Num = ThisInstance.Instance_Num
      ThisTranslation.Lang_Name    = (IF LanguageName:SCREEN-VALUE IN FRAME ProcsFrame NE "" THEN
                                         LanguageName:SCREEN-VALUE IN FRAME ProcsFrame
                                      ELSE "").
  END.  /* If This Translation wasn't available */

  ASSIGN ThisTranslation.Trans_String = trg
         ThisTranslation.Last_Change  = INT(TODAY) + (TIME / 100000)
         translationROWID    = ROWID(ThisTranslation).

  result = ThisBuffer:DELETE-RESULT-LIST-ENTRY().
  FIND ThisString WHERE ROWID(ThisString) = stringROWID.
  FIND ThisInstance WHERE ROWID(ThisInstance) = instanceROWID.
  FIND ThisTranslation WHERE ROWID(ThisTranslation) = translationROWID.
  result = ThisBuffer:CREATE-RESULT-LIST-ENTRY().

  ASSIGN ThisBuffer:REFRESHABLE IN FRAME ProcsFrame = TRUE.

  RUN Repo (stringROWID, instanceROWID, translationROWID, ?).
  RUN updateGloss.

END PROCEDURE. /* Store-Long-String */

PROCEDURE updateGloss:
  DEFINE VARIABLE ss            AS CHARACTER                         NO-UNDO.
  DEFINE VARIABLE st            AS CHARACTER                         NO-UNDO.
  DEFINE VARIABLE did-trans     AS LOGICAL                           NO-UNDO.
    IF s_glossary = "":U OR s_glossary = "None":U THEN
    DO WITH FRAME {&FRAME-NAME}:
      /* Attempt to find the glossary for the visible language */
      FIND xlatedb.XL_Glossary WHERE
           NUM-ENTRIES(xlatedb.XL_Glossary.GlossaryType,"/":U) > 1 AND
           ENTRY(2, xlatedb.XL_Glossary.GlossaryType, "/":U) = LanguageName:SCREEN-VALUE
           NO-LOCK NO-ERROR.
      IF AVAILABLE xlatedb.XL_Glossary THEN s_glossary = xlatedb.XL_Glossary.GlossaryName.
    END. /* s_glossary = "" OR None */

    IF s_Glossary NE "":U AND s_Glossary NE "None":U THEN
    DO:
      ASSIGN ss = REPLACE(ThisString.Original_String:SCREEN-VALUE IN BROWSE ThisBuffer, "&":U, "":U)
             st = REPLACE(ThisTranslation.Trans_string:SCREEN-VALUE, "&":U, "":U).
      IF st NE "":U AND st NE ? AND st NE "?":U THEN
      DO:
        FIND xlatedb.XL_GlossDet WHERE xlatedb.XL_GlossDet.GlossaryName = s_Glossary AND
             XLATEDB.XL_GlossDet.ShortSrc     BEGINS SUBSTRING(ss,1,63,"RAW":U) AND
             XLATEDB.XL_GlossDet.ShortTarg    BEGINS SUBSTRING(st,1,63,"RAW":U) AND
             XLATEDB.XL_GlossDet.SourcePhrase MATCHES ss AND
             XLATEDB.XL_GlossDet.TargetPhrase MATCHES st NO-LOCK NO-ERROR.
        IF NOT AVAILABLE xlatedb.XL_GlossDet THEN
        DO TRANSACTION:
          /* Add this to the glossary */
          CREATE xlatedb.XL_GlossDet.
          ASSIGN XLATEDB.XL_GlossDet.GlossaryName         = s_Glossary
                 XLATEDB.XL_GlossDet.GlossaryType         = "D":U
                 XLATEDB.XL_GlossDet.ModifiedByTranslator = NO
                 XLATEDB.XL_GlossDet.ShortSrc             = SUBSTRING(ss,1,63,"RAW":U)
                 XLATEDB.XL_GlossDet.ShortTarg            = SUBSTRING(st,1,63,"RAW":U)
                 XLATEDB.XL_GlossDet.SourcePhrase         = ss
                 XLATEDB.XL_GlossDet.TargetPhrase         = st
                 did-trans                                = YES.
        END. /* If not already in the glossary */
        IF did-trans AND VALID-HANDLE(_hGloss) THEN RUN OpenQuery IN _hGloss.
      END.  /* if st is a real translation */
    END. /* If a glossary is present */

END PROCEDURE.
