Changeset 1394 for trunk/dll/strutil.c


Ignore:
Timestamp:
Feb 5, 2009, 5:17:25 AM (17 years ago)
Author:
Steven Levine
Message:

Ticket 340: Convert GetPString to use STRINGTABLE.

Drop fm3dll.str and mkstr.exe from makefiles and wpi builders

Convert many functions to expect PCSZ arguments.
Correct walk, compare and dirsizes dialog setups to ignore saved dialog size
Drop copyright.c logic from makefile

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/dll/strutil.c

    r1213 r1394  
    44  $Id$
    55
    6   External strings file support
     6  External strings support - stored in STRINGTABLE
    77
    88  Copyright (c) 1993-98 M. Kimes
    9   Copyright (c) 2006, 2008 Steven H. Levine
     9  Copyright (c) 2006, 2009 Steven H. Levine
    1010
    1111  22 Jul 06 SHL Comments
    1212  20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
    1313  05 Jan 08 SHL Rename from string.c to avoid string.h conflict
     14  03 Feb 09 SHL Switch to STRINGTABLE and const return
    1415
    1516***********************************************************************/
     
    1718#include <stdio.h>
    1819#include <share.h>
     20#include <string.h>
     21
     22#define INCL_DOSPROCESS                 // DosSleep
    1923
    2024#include "fm3dll.h"
    2125#include "fm3str.h"
    2226#include "init.h"                       // Data declaration(s)
     27#include "mainwnd.h"                    // FM3ModHandle
     28#include "wrappers.h"
     29#include "errutil.h"
    2330#include "strutil.h"
    2431#include "version.h"
    2532
    26 extern PSZ NullStr;                     // 05 Jan 08 SHL fixme to be in some .h
    27 
    28 static char **strs, *str;
    29 static ULONG numStr;
    30 
    31 //== LoadStrings() load strings from file ==
    32 
    33 BOOL LoadStrings(char *filename)
     33static PSZ pszSrcFile = __FILE__;
     34
     35//== GetPString() return a readonly pointer to the requested string in memory ==
     36
     37PCSZ GetPString(ULONG id)
    3438{
    35   BOOL ok = FALSE;
    36   ULONG size, len, totalsize;
    37   USHORT vermajor = 0, verminor = 0;
    38   register char *p;
    39   register ULONG x;
    40   FILE *fp;
    41   APIRET rc;
    42 
    43   /* Load strings from requested file or FM3RES.STR
    44    * with some quiet error-checking.
    45    * Return TRUE on success, FALSE on error.
    46    */
    47 
    48   if (!filename)
    49     filename = "FM3RES.STR";
    50   numStr = 0;
    51   if (str)
    52     DosFreeMem(str);
    53   strs = NULL;
    54   str = NULL;
    55 
    56   fp = _fsopen(filename, "rb", SH_DENYWR);
    57   if (fp) {
    58     if (fread(&numStr,
    59               sizeof(numStr),
    60               1,
    61               fp) &&
    62         numStr == IDS_NUMSTRS &&
    63         fread(&len, sizeof(len), 1, fp) &&
    64         fread(&vermajor, sizeof(vermajor), 1, fp) &&
    65         fread(&verminor, sizeof(verminor), 1, fp) &&
    66         (vermajor >= VERMAJORBREAK &&
    67          (vermajor > VERMAJORBREAK || verminor >= VERMINORBREAK))) {
    68       fseek(fp, 0, SEEK_END);
    69       size = ftell(fp) - ((sizeof(ULONG) * 2) + (sizeof(USHORT) * 2));
    70       if (size && size == len) {
    71         fseek(fp, (sizeof(ULONG) * 2) + (sizeof(USHORT) * 2), SEEK_SET);
    72         /* NOTE:  Make one memory object for both str and strs
    73          * for efficiency.
    74          */
    75         totalsize = size + sizeof(ULONG);
    76         totalsize += (totalsize % sizeof(ULONG));
    77         len = totalsize;
    78         totalsize += (numStr * sizeof(char *));
    79         totalsize += 4;
    80         rc = DosAllocMem((PPVOID) & str, totalsize,
    81                          PAG_COMMIT | PAG_READ | PAG_WRITE);
    82         if (!rc && str) {
    83           strs = (char **)(str + len);
    84           if (fread(str, 1, size, fp) == size) {
    85             p = str;
    86             for (x = 0; x < numStr; x++) {
    87               if (p - str >= size)
    88                 break;
    89               strs[x] = p;
    90               while (*p)
    91                 p++;
    92               p++;
    93             }
    94             if (x == numStr)
    95               ok = TRUE;
     39  PSZ psz;
     40  LONG l;
     41  CHAR sz[257];
     42  ULONG ulNewFirstId;
     43  ULONG ulNewLastId;
     44
     45  static PSZ *pLoadedStrings;
     46  static ULONG ulFirstId;
     47  static ULONG ulLastId;
     48
     49  // Strings that must be combined because stringtable items limited to 256
     50  static struct LongString {
     51    ULONG id;
     52    ULONG sub_id;
     53  } LongStrings[] = {
     54    {IDS_SUGGEST1TEXT, IDS_SUGGEST1TEXT1},
     55    {IDS_SUGGEST1TEXT, IDS_SUGGEST1TEXT2},
     56    {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT1},
     57    {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT2},
     58    {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT3},
     59    {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT4},
     60    {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT5},
     61    {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT6},
     62    {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT7},
     63    {IDS_INIBINARYDATASKIPTEXT, IDS_INIBINARYDATASKIPTEXT1},
     64    {IDS_INIBINARYDATASKIPTEXT, IDS_INIBINARYDATASKIPTEXT2},
     65    {IDS_INSTANTHELPTEXT, IDS_INSTANTHELPTEXT1},
     66    {IDS_INSTANTHELPTEXT, IDS_INSTANTHELPTEXT2},
     67    {IDS_FSDERRORTEXT, IDS_FSDERRORTEXT1},
     68    {IDS_FSDERRORTEXT, IDS_FSDERRORTEXT2},
     69    {IDS_LANERRORTEXT, IDS_LANERRORTEXT1},
     70    {IDS_LANERRORTEXT, IDS_LANERRORTEXT2},
     71    {IDS_MAKESHADOWHELPTEXT, IDS_MAKESHADOWHELPTEXT1},
     72    {IDS_MAKESHADOWHELPTEXT, IDS_MAKESHADOWHELPTEXT2},
     73    {IDS_UNDELETEHELPTEXT, IDS_UNDELETEHELPTEXT1},
     74    {IDS_UNDELETEHELPTEXT, IDS_UNDELETEHELPTEXT2},
     75    {IDS_KILLPROCHELPTEXT, IDS_KILLPROCHELPTEXT1},
     76    {IDS_KILLPROCHELPTEXT, IDS_KILLPROCHELPTEXT2},
     77    {IDS_ARCNOTTHERETEXT, IDS_ARCNOTTHERETEXT1},
     78    {IDS_ARCNOTTHERETEXT, IDS_ARCNOTTHERETEXT2},
     79    {IDS_FM2CMDHELPTEXT, IDS_FM2CMDHELPTEXT1},
     80    {IDS_FM2CMDHELPTEXT, IDS_FM2CMDHELPTEXT2},
     81    {IDS_FM2CMDHELPTEXT, IDS_FM2CMDHELPTEXT3}
     82  };
     83
     84  static UINT cLongStrings = sizeof(LongStrings) / sizeof(struct LongString);
     85
     86  static volatile INT cBusy;            // Need to be MT-safe
     87  static ULONG ulDbgId;                 // 13 Jan 09 SHL fixme to be gone?
     88  static UINT uDbgState;                // 03 Feb 09 SHL fixme to be gone?
     89  static ULONG ulDbgTid;                // 13 Jan 09 SHL fixme to be gone?
     90
     91  UINT c;
     92  // 23 Jan 09 SHL fixme to use SMP safe inc/dec?
     93  extern void SMPSafeInc(void);
     94  extern void SMPSafeDec(void);
     95  #pragma aux SMPSafeInc = "lock inc cBusy" modify exact [];
     96  #pragma aux SMPSafeDec = "lock dec cBusy" modify exact [];
     97  // SMPSafeInc();
     98  for (c = 0; ; c++) {
     99    if (++cBusy == 1)
     100      break;
     101    cBusy--;
     102    // Hold off 1 cycle before reporting since some contention expected
     103    if (c == 1)
     104      DbgMsg(pszSrcFile, __LINE__, "GetPString(%lu) waiting for tid %lu GetPString(%lu), state=%u", id, ulDbgTid, ulDbgId, uDbgState);
     105    DosSleep(1);                        // Let current owner finish
     106  }
     107  if (c > 1)
     108    DbgMsg(pszSrcFile, __LINE__, "continuing with GetPString(%lu) after tid %lu GetPString(%lu), state=%u", id, ulDbgTid, ulDbgId, uDbgState);
     109
     110  // Remember id and thread ordinal for diagnosing MT hangs
     111  // Use fast DosGetInfoBlocks to ensure debug logic does not change timing
     112  {
     113    extern PTIB2 GetPTIB2(void);
     114    #pragma aux GetPTIB2 = "mov eax,fs:[12]" value [eax];
     115    // PIB *ppib;
     116    // TIB *ptib;
     117    TIB2 *ptib2 = GetPTIB2();
     118    // APIRET apiret = DosGetInfoBlocks(&ptib, &ppib);
     119    ulDbgId = id;
     120    // ulDbgTid = apiret == 0 ? ptib->tib_ptib2->tib2_ultid : 0;
     121    ulDbgTid = ptib2->tib2_ultid;
     122  }
     123
     124  // DbgMsg(pszSrcFile, __LINE__, "Fetching %lu", id);
     125
     126  // If string already loaded, return it now
     127  if (id >= ulFirstId &&
     128      id <= ulLastId &&
     129      pLoadedStrings &&
     130      (psz = pLoadedStrings[id - ulFirstId]) != NULL) {
     131    cBusy--;
     132    if (((ULONG)psz & 0xffff0000) == 0)
     133      DbgMsg(pszSrcFile, __LINE__, "id %lu corrupted %p", id, psz);
     134    // DbgMsg(pszSrcFile, __LINE__, "id %lu \"%s\"", id, psz ? psz : "(null)");
     135    return psz;
     136  }
     137
     138  // Try to load
     139  // 11 Jan 09 SHL fixme to use global HAB?
     140  uDbgState = 1;
     141  l = WinLoadString((HAB)NULL, FM3ModHandle, id, sizeof(sz), sz);
     142  uDbgState = 2;
     143
     144  if (l != 0) {
     145    psz = xstrdup(sz, pszSrcFile, __LINE__);
     146    if (!psz) {
     147      cBusy--;
     148      return NullStr;
     149    }
     150  }
     151  else {
     152    // Assume string must be built from multiple strings - find first
     153    UINT i;
     154    psz = NULL;
     155    for (i = 0; i < cLongStrings && LongStrings[i].id != id; i++);      // Scan
     156
     157    if (i < cLongStrings) {
     158      // Combine stringtable items to build long string
     159      // DbgMsg(pszSrcFile, __LINE__, "Building long string %lu", id);
     160      for (; LongStrings[i].id == id; i++) {
     161        uDbgState = 3;
     162        l = WinLoadString((HAB)NULL, FM3ModHandle, LongStrings[i].sub_id, sizeof(sz), sz);
     163        uDbgState = 4;
     164        if (l == 0) {
     165          cBusy--;
     166          Runtime_Error(pszSrcFile, __LINE__, "string %lu missing", LongStrings[i].sub_id);
     167          xfree(psz, pszSrcFile, __LINE__);
     168          return NullStr;
     169        }
     170        if (!psz) {
     171          // Remember 1st string
     172          psz = strdup(sz);
     173          if (!psz) {
     174            cBusy--;
     175            return NullStr;
    96176          }
    97           if (ok)
    98             /* set pages to readonly */
    99             DosSetMem(str, totalsize, PAG_COMMIT | PAG_READ);
    100177        }
    101       }
    102     }
    103     fclose(fp);
    104   }
    105 
    106   if (!ok) {
    107     numStr = 0;
    108     if (str)
    109       DosFreeMem(str);
    110     str = NULL;
    111     strs = NULL;
    112   }
    113 
    114   return ok;
     178        else {
     179          // Append string
     180          UINT curLen = strlen(psz);
     181          PSZ psz2 = xrealloc(psz, curLen + l + 1, pszSrcFile, __LINE__);
     182          if (!psz2) {
     183            xfree(psz, pszSrcFile, __LINE__);
     184            cBusy--;
     185            return NullStr;
     186          }
     187          memcpy(psz2 + curLen, sz, l); // Append
     188          *(psz2 + curLen + l) = 0;     // Terminate
     189          psz = psz2;                   // Remember
     190          l += curLen;
     191        }
     192      } // while
     193    } // if long
     194  } // if loaded
     195
     196  if (l == 0) {
     197    DbgMsg(pszSrcFile, __LINE__, "Error loading %lu", id);
     198    sprintf(sz, "** Error loading id %lu **", id);
     199    psz = xstrdup(sz, pszSrcFile, __LINE__);
     200    if (psz)
     201      l = strlen(sz);
     202    else
     203      psz = NullStr;            // Oh heck
     204  }
     205
     206  uDbgState = 5;
     207  // Add to cache
     208  // DbgMsg(pszSrcFile, __LINE__, "Caching %lu", id);
     209
     210  // Calculate new array limits
     211  if (!pLoadedStrings) {
     212    ulNewFirstId = id;
     213    ulNewLastId = id;
     214    ulFirstId = id;
     215    ulLastId = id;
     216  }
     217  else {
     218    ulNewFirstId = id < ulFirstId ? id : ulFirstId;
     219    ulNewLastId = id > ulLastId ? id : ulLastId;
     220  }
     221
     222  if (ulNewFirstId != ulFirstId ||
     223      ulNewLastId != ulLastId ||
     224      !pLoadedStrings) {
     225    PSZ *pNewLoadedStrings;
     226    // DbgMsg(pszSrcFile, __LINE__, "Reallocating for %lu", id);
     227    pNewLoadedStrings = xrealloc(pLoadedStrings,
     228                                 (ulNewLastId - ulNewFirstId + 1) * sizeof(PSZ),
     229                                 pszSrcFile, __LINE__);
     230    if (!pNewLoadedStrings) {
     231      cBusy--;
     232      Runtime_Error(pszSrcFile, __LINE__, "realloc failed");
     233      xfree(psz, pszSrcFile, __LINE__);
     234      return NullStr;
     235    }
     236    // Align existing entries and zero fill unused entries as needed
     237    if (ulNewFirstId < ulFirstId) {
     238      // Move room for new entries at head of array
     239      memmove(pNewLoadedStrings + (ulFirstId - ulNewFirstId),
     240             pNewLoadedStrings,
     241             (ulLastId - ulFirstId + 1) * sizeof(PSZ));
     242      // Null unused placeholder entries
     243      if (ulFirstId - ulNewFirstId > 1)
     244        memset(pNewLoadedStrings + 1, 0, (ulFirstId - ulNewFirstId - 1) * sizeof(PSZ));
     245    }
     246    if (ulNewLastId - ulLastId > 1) {
     247      // Null unused placeholder entries
     248      memset(pNewLoadedStrings + (ulLastId - ulNewFirstId + 1),
     249             0,
     250             (ulNewLastId - ulLastId - 1) * sizeof(PSZ));
     251    }
     252    pLoadedStrings = pNewLoadedStrings;
     253    ulFirstId = ulNewFirstId;
     254    ulLastId = ulNewLastId;
     255  }
     256
     257  uDbgState = 6;
     258  pLoadedStrings[id - ulFirstId] = psz;
     259  cBusy--;
     260  // DbgMsg(pszSrcFile, __LINE__, "id %lu \"%s\"", id, psz ? psz : "(null)");
     261  return psz;
    115262}
    116263
    117 //== GetPString() return a readonly pointer to the requested string in memory ==
    118 
    119 char *GetPString(ULONG id)
    120 {
    121   return id < numStr && str && strs && strs[id] ? strs[id] : NullStr;
    122 }
    123 
    124 //== StringsLoaded() return TRUE is strings loaded
    125 
    126 BOOL StringsLoaded(void)
    127 {
    128   return numStr && str && strs;
    129 }
    130 
    131264#pragma alloc_text(STRINGS,LoadStrings,GetPString)
Note: See TracChangeset for help on using the changeset viewer.