Beispiel #1
0
/************************************************************
 *
 *  FUNCTION: ErrAlertCustom
 *		NOT present in PalmOS <= 3.0
 *
 *  DESCRIPTION: 
 *
 *		This routine can be used to display an alert for normal
 *		run-time errors that occur in an application. This is most
 *		likely to be used by network applications to display errors
 *		like "server not found", "network down", etc. In most cases
 *		the alert will simply have an OK button and execution will
 *		continue when the OK button is pressed.
 *
 *		This routine will lookup the text assoicated with the given
 *		error code 'errCode' and display that in the Alert. If 'errMsgP'
 *		is not nil however, that text will be used in place of the
 *		text associated with 'errCode'. In addition, the 'preMsgP' and
 *		'postMsgP' text strings, if specified, will be pre-pended and
 *		post-pended respectively. 
 *
 *		The text associated with an error code is looked up from a
 *		'tSTL' resource using the SysErrString() routine. A 'tSTL'
 *		resource contains a list of strings that can be looked up
 *		by index. All of the system defined error code strings are
 *		defined in the 'tSTL' resources numbered 10000 -> (10000+errClass) where
 *		'errClass' is the upper 8 bits of the error number. For example,
 *		the error strings for the DataManager (0x0200 -> 0x02FF) are
 *		found in 'tSTL' resource number 10002. 
 *
 *		The text associated with application specific error codes
 *		are always numbered 0x8000 -> 0x80FF (appErrorClass + X). These
 *		are always looked up from a 'tSTL' resource number 0 contained
 *		within the application itself. 
 *
 *		NOTE: The following paragraph is NOT IMPLEMENTED YET: 
 *		For system error codes that correspond to Libraries (like
 *		netErrorClass, inetErrorClass, etc.) This routine will first
 *		check for a 'tSTL' #0 resource in the library database itself before
 *		checking the appropriately numbered system 'tSTL' resource. In
 *		this way, libraries can contain their own error strings and don't
 *		have to rely on the error strings in the system resource file.
 *		Unfortunately, there is no programmatic way of determining if an
 *		error number corresponds to a library or not. This routine thus
 *		must be updated whenever a new error class is defined for a new
 *		library. 
 *		
 *
 *    Button Command Strings
 *		---------------------------------------------------------------
 *		By default, only an OK button will be displayed in the alert and
 *		no particular action will be taken when the OK button is pressed.
 *		But, a cancel button can be added and special actions can be
 *		specified through control strings inserted in the front of the
 *		error text. Here's the format of the control sequence:
 *
 *		"<" <btnID> [<cmdChar> <cmdVars>] ">"
 *
 *		The <btnID> can be either 0 or 1. 0 is always an OK button and
 *		1 is a Cancel button. If a control sequence with a btnID if 1
 *		is not specified, then the alert will not show a Cancel button. 
 *
 *		The <cmdChar> is a single character command. The only two currently
 *		supported are:  'K' and 'S'. The 'K' command will cause a key event
 *		to be posted to the event queue and the 'S' command will cause 
 *		an application switch through posting a quit event. 
 *
 *		Here's an example text string that specifies an OK and a Cancel button
 *		and makes a switch to the Memo application if the user hits the OK
 *		button:
 *			"<0Smemoappl0000><1>Hit OK to switch to Memos, Cancel to ignore"
 *
 *		Here are the formats of the commands:
 *
 *		Key Command: "K" <ascii> <keyCode> <modifiers>
 *			where <ascii> <keyCode>, and <modifiers> are 4 character hex
 *			strings that specify the various fields of the key event. For
 *			example:
 *				"K011300000008"
 *			will generate a key event with an ascii code of 0x0113 (backlightChr)
 *			a keyCode of 0x0000, and a modifiers of 0x0008 (commandKeyMask).
 *
 *		SwitchApp command: "S" <creator> <type> <launchCmd>
 *			where <creator> and <type> are the 4 character creator/type
 *			of the new application to switch to. 
 *			launchCmd is a 4 character hex string that specifies the
 *			action code to send the application: For example:
 *				"Smemoappl0004" 
 *			will make a call to SysUIAppSwitch to have it launch the
 *			Memo application with a launch code of 4. 
 *		
 *
 *    Aliased Error Strings
 *		---------------------------------------------------------------
 *		Another possible control sequence that can appear as the error
 *		text is:
 *
 *			"<" "*" <aliasErrCode> ">"
 *
 *		This sequence acts as an alias to another error code. The <aliasErrCode>
 *		is a 4 character hex string representing the error code to alias to.
 *		This is useful when two or more error codes should display the
 *		same error string. 
 *		example:
 *			"<*1437>"
 *		will make this routine lookup the error string used by the 0x1437
 *		error code. 
 *
 *
 *  PARAMETERS: 
 *		errCode		-> 16 bit error code to display
 *		errMsgP		-> if not NULL, then this text will be used in place
 *								of the associated 'errCode' text from the string
 *								resource
 *		preMsgP		-> if not NULL, text to prepend to error text
 *		postMsgP		-> if not NULL, text to append to error text
 *		
 *
 *  RETURNS: index of button pressed:
 *						0 is always the OK button
 *						1 is the Cancel button, if present. 
 *
 *  CREATED: 2/25/98
 *
 *  BY: Ron Marianetti
 *
 *************************************************************/
UInt16	ErrAlertCustom(Err errCode, Char * errMsgP, Char * preMsgP, 
			Char *	postMsgP)
{
	const		Int16	maxErrLen = errMaxMsgLength+1;
	Char *	errBufP = 0;
	UInt16	result = 0;
	Char		emptyString[1];
	UInt16	index;
	UInt16	resID;
	Char *	cP;
	UInt16	alertID;
	Err		tmpErr;
	Int16		aliasIndex;
	Err		tmpErrCode;
	Char		neumonicString [maxErrNeumonicLength + 1];
	
	// Information parsed from error Text
	Boolean					parseErr = false;
	Boolean					hasCancel = false;
	Char *					okCmdP = 0;
	Char *					cancelCmdP = 0;
	Char *					cmdP = 0;
	
	UInt16						keyAscii, keyCode, keyMod;
	UInt32						appCreator, appType;
	
	// Used for doing appSwitch
	DmSearchStateType		dmState;
	UInt16						cardNo;
	LocalID					dbID;
	UInt16						launchCmd;
	UInt16						okAlertID;
	UInt16						okCancelAlertID;
	UInt16						cancelAlertID;
	UInt16						errClass;
	
	
	
	
	// Allocate a buffer to hold the error text
	errBufP = MemPtrNew(maxErrLen);
	ErrNonFatalDisplayIf (!errBufP, "out of memory");
	if (!errBufP) goto Exit;
	
	//==============================================================
	// Very Very First, Determine the buttons to use.
	//==============================================================
	errClass = errCode & 0xFF00;
	// Must use an If statement here because the complier otherwise generates code that 
	// cannot link
	if ((errClass==errInfoClass) || (errClass==netErrorClass) || (errClass==inetErrorClass) ||
		(errClass==webErrorClass) || (errClass==pwrErrorClass) )
		
	{
	    okAlertID 			= InfoOKAlert;
	    okCancelAlertID 	= InfoOKCancelAlert;
	    cancelAlertID 	= InfoCancelAlert;
	    if (errClass == errInfoClass) errCode = 0;  // ignore errors in this class
	} else
	{
	    okAlertID 			= ErrOKAlert;
	    okCancelAlertID 	= ErrOKCancelAlert;
	    cancelAlertID 	= ErrCancelAlert;
	}
	
	//==============================================================
	// First, lookup the error text if not specified in the 'errMsgP'
	//  parameter
	//==============================================================
	if (!errMsgP) {
		errMsgP = errBufP;
		
		tmpErrCode = errCode;
		
		// Loop till we get the error string. If we find an
		//  alias escape code, we need to follow that to get
		//  the error string. We only follow a limited number of
		//  aliases in order to avoid recursion. 
		for (aliasIndex = 0; aliasIndex < 5; aliasIndex++) {
		
			// Get the index of the error string
			index = tmpErrCode & 0x00FF;
			
			//----------------------------------------------------------
			// Compute which resource ID to fetch
			//----------------------------------------------------------
			// If it's not an application specific error code, get it
			//  out of the appropriate system string resource. 
			if ((tmpErrCode & 0xFF00) != appErrorClass) 
				resID = sysResIDErrStrings + ((tmpErrCode >> 8) & 0x00FF);
				
			// For application custom errors, get it out of the 
			//  #0 resource in the application database. 
			else
				resID = 0;
				
				
			//----------------------------------------------------------
			// Read in the error text string
			//----------------------------------------------------------
			cP = SysStringByIndex(resID, index, errBufP, maxErrLen);
			if (!cP) 
				errBufP[0] = 0;
				
			// If it's an alias string, follow it
			if (cP[0] == '<' && cP[1] == '*') 
				tmpErrCode = Prv4HToI(cP+2);
			else
				break; // out of for(aliasIndex; ;) loop
			}
Beispiel #2
0
/***********************************************************************
 *
 * FUNCTION:    RepeatDrawDescription
 *
 * DESCRIPTION: This routine draws the text description of the current
 *              repeat type and frequency.
 *
 *              The description is created from a template string.  The
 *              repeat type and frequency determines which template is
 *              used.  The template may contain one or more of the
 *              following token:
 *                   ^d - day name (ex: Monday)
 *							^f - frequency
 *                   ^x - day of the month ordinal number (ex: 1st - 31th)
 *                   ^m - month name (ex: July)
 *                   ^w - week ordinal number (1st, 2nd, 3rd, 4th, or last)
 *
 * PARAMETERS:  frm - pointer to the repeat dialog box
 *
 * RETURNED:    nothing
 *
 ***********************************************************************/
void RepeatDrawDescription(FormType* frm) {
  UInt8 repeatOn;
  UInt16 i;
  UInt16 len;
  UInt16 freq;
  UInt16 dayOfWeek;
  UInt16 templateId = repeatNoneString;
  UInt16 repeatOnCount = 0;
  Char* descP = NULL;
  Char* resP = NULL;
  Char* saveResP = NULL;
  MemHandle descH = NULL;
  MemHandle resH = NULL;
  RepeatInfoType repeat;
  FieldType* fld = GetObjectPointer(frm, RepeatDescField);

  FldEraseField (fld);

  /* Get the current setting of the repeat ui gadgets. */
  RepeatGetUIValues(frm, &repeat);
  
  /*
  ** Determine which template string to use.  The template string is
  ** used to format the description string. Note that we could add
  ** a soft constant which tells us whether we need to use different
  ** strings for freq == 1 case (depends on language), thus saving space.
  */
  freq = repeat.repeatFrequency;
  switch (repeat.repeatType) {
  case repeatNone:
    templateId = repeatNoneString;
    break;
    
  case repeatHourly:
    if (freq == 1)
      /* "Every hour" */
      templateId = everyHourRepeatString;
    else
      /* "Every [other | 2nd | 3rd...] hour" */
      templateId = hourlyRepeatString;
    break;
    
  case repeatDaily:
    if (freq == 1)
      /* "Every day" */
      templateId = everyDayRepeatString;
    else
      /* "Every [other | 2nd | 3rd...] day" */
      templateId = dailyRepeatString;
    break;
    
  case repeatWeekly:
    if (freq == 1)
      /* "Every week on [days of week]" */
      templateId = everyWeekRepeat1DayString;
    else
      templateId = weeklyRepeat1DayString;
    
    /*
    ** Generate offset to appropriate string id,
    ** based on # of days that we need to append.
    */
    for (i = 0; i < daysInWeek; i++) {
      if (repeat.repeatOn & (1 << i) ) 
	repeatOnCount++;
    }
    templateId += repeatOnCount - 1;
    break;

  case repeatMonthlyByDate:
    if (freq == 1)
      /* "The ^w ^d of every month" */
      templateId = everyMonthByDateRepeatString;
    else
      templateId = monthlyByDateRepeatString;
    break;
    
  case repeatMonthlyByDay:
    if (freq == 1)
      templateId = everyMonthByDayRepeatString;
    else
      templateId = monthlyByDayRepeatString;
    break;
    
  case repeatYearly:
    if (freq == 1)
      templateId = everyYearRepeatString;
    else
      templateId = yearlyRepeatString;
    break;
    
  default:
    ErrNonFatalDisplay("Unknown repeat type");
    break;
  }

  /*
  ** Allocate a block to hold the description and copy the template
  ** string into it.
  */
  resH = DmGetResource(strRsc, templateId);
  resP = MemHandleLock(resH);
  descH = MemHandleNew(MemPtrSize(resP));
  ASSERT(descH);
  descP = MemHandleLock(descH);
  StrCopy(descP, resP);
  MemHandleUnlock(resH);
  
  /* Substitute the month name string for the month name token. */
  resH = DmGetResource(strRsc, repeatMonthNamesString);
  resP = MemHandleLock(resH);
  for (i = 1; i < d.frm_date.month; i++)
    resP = StrChr(resP, spaceChr) + 1;
  len = StrChr(resP, spaceChr) - resP;
  descP = SubstituteStr(descP, monthNameToken, resP, len);
  MemHandleUnlock(resH);

  /* Substitute the day name string for the day name token. */
  if ((repeatOnCount == 1) || (repeat.repeatType == repeatMonthlyByDay))
    templateId = repeatFullDOWNamesString;
  else
    templateId = repeatShortDOWNamesString;
  
  resH = DmGetResource(strRsc, templateId);
  resP = MemHandleLock(resH);
  if (repeat.repeatType == repeatWeekly) {
    dayOfWeek = repeat.repeatStartOfWeek;
    repeatOn = repeat.repeatOn;
    saveResP = resP;
    while (StrStr (descP, dayNameToken)) {
      for (i = 0; i < daysInWeek; i++) {
	if (repeatOn & (1 << dayOfWeek)) {
	  repeatOn &= ~(1 << dayOfWeek);
	  break;
	}
	dayOfWeek = (dayOfWeek + 1 + daysInWeek) % daysInWeek;
      }
      resP = saveResP;
      for (i = 0; i < dayOfWeek; i++)
	resP = StrChr(resP, spaceChr) + 1;
      
      len = StrChr(resP, spaceChr) - resP;
      descP = SubstituteStr(descP, dayNameToken, resP, len);
    }
  } else {
    dayOfWeek = DayOfWeek (d.frm_date.month, d.frm_date.day,
			   d.frm_date.year/* + firstYear*/);
    for (i = 0; i < dayOfWeek; i++)
      resP = StrChr(resP, spaceChr) + 1;
    len = StrChr(resP, spaceChr) - resP;
    descP = SubstituteStr(descP, dayNameToken, resP, len);
  }
  MemHandleUnlock (resH);

  /*
  ** Substitute the repeat frequency string for the frequency token. Note that
  ** we do something special for 2nd (other), since the gender of 'other' changes
  ** for some languages, depending on whether the next word is day, month, week,
  ** or year.
  */
  if (freq == 2) {
    Char otherFreqName[16];
    const UInt16 index = repeat.repeatType - repeatNone;
    SysStringByIndex(freqOrdinal2ndStrlID, index, otherFreqName, sizeof(otherFreqName));
    descP = SubstituteStr(descP, frequenceToken, otherFreqName, StrLen(otherFreqName));
  } else {
    resH = DmGetResource(strRsc, freqOrdinalsString);
    resP = MemHandleLock(resH);
    for (i = 1; i < freq; i++)
      resP = StrChr(resP, spaceChr) + 1;
    len = StrChr(resP, spaceChr) - resP;
    descP = SubstituteStr(descP, frequenceToken, resP, len);
    MemHandleUnlock(resH);
  }

  /*
  ** Substitute the repeat week string (1st, 2nd, 3rd, 4th, or last)
  ** for the week ordinal token.
  */
  if (repeat.repeatType == repeatMonthlyByDay) {
    resH = DmGetResource(strRsc, weekOrdinalsString);
    resP = MemHandleLock(resH);
    for (i = 0; i < repeat.repeatOn / daysInWeek; i++)
      resP = StrChr (resP, spaceChr) + 1;
    len = StrChr(resP, spaceChr) - resP;
    descP = SubstituteStr(descP, weekOrdinalToken, resP, len);
    MemHandleUnlock(resH);
  } else {
    /* make sure the week ordinal token really doesn't appear */
    ErrNonFatalDisplayIf(StrStr(descP, weekOrdinalToken) != NULL, "week ordinal not substituted");
  }

  /*
  ** Substitute the repeat date string (1st, 2nd, ..., 31th) for the
  ** day ordinal token.
  */
  resH = DmGetResource(strRsc, dayOrdinalsString);
  resP = MemHandleLock(resH);
  for (i = 1; i < d.frm_date.day; i++)
    resP = StrChr(resP, spaceChr) + 1;
  len = StrChr(resP, spaceChr) - resP;
  descP = SubstituteStr(descP, dayOrdinalToken, resP, len);
  MemHandleUnlock(resH);

  /* Draw the description. */
  MemHandleUnlock(descH);
  FldFreeMemory(fld);
  FldSetTextHandle(fld, descH);
  FldDrawField(fld);
}