@@ -223,6 +223,15 @@ FreeImage_IsLittleEndian() {
223223
224224// ----------------------------------------------------------------------
225225
226+ struct MessageProcessContext
227+ {
228+ void * ctx{ nullptr };
229+ FreeImage_ProcessMessageFunction func{ nullptr };
230+ };
231+
232+ thread_local MessageProcessContext g_process_message{ };
233+
234+
226235static FreeImage_OutputMessageFunction freeimage_outputmessage_proc{};
227236static FreeImage_OutputMessageFunctionStdCall freeimage_outputmessagestdcall_proc{};
228237
@@ -238,108 +247,98 @@ FreeImage_SetOutputMessageStdCall(FreeImage_OutputMessageFunctionStdCall omf) {
238247
239248void DLL_CALLCONV
240249FreeImage_OutputMessageProc (int fif, const char *fmt, ...) {
241- const int MSG_SIZE = 512 ; // 512 bytes should be more than enough for a short message
250+ constexpr size_t MSG_SIZE = 512 ;
242251
243- if (fmt && (freeimage_outputmessage_proc || freeimage_outputmessagestdcall_proc)) {
244- char message[MSG_SIZE];
245- memset (message, 0 , MSG_SIZE);
246-
247- // initialize the optional parameter list
252+ if (fmt && (g_process_message.func || freeimage_outputmessage_proc || freeimage_outputmessagestdcall_proc)) {
253+ FIMESSAGE message{ static_cast <FREE_IMAGE_FORMAT>(fif), FISEV_WARNING };
254+ message.text .resize (MSG_SIZE);
248255
249256 va_list arg;
250257 va_start (arg, fmt);
251258
252- // check the length of the format string
253-
254- int str_length = (int )( (strlen (fmt) > MSG_SIZE) ? MSG_SIZE : strlen (fmt) );
255-
256- // parse the format string and put the result in 'message'
257-
258- for (int i = 0 , j = 0 ; i < str_length; ++i) {
259- if (fmt[i] == ' %' ) {
260- if (i + 1 < str_length) {
261- switch (tolower (fmt[i + 1 ])) {
262- case ' %' :
263- message[j++] = ' %' ;
264- break ;
265-
266- case ' o' : // octal numbers
267- {
268- char tmp[16 ];
269-
270- _itoa (va_arg (arg, int ), tmp, 8 );
271-
272- strcat (message, tmp);
259+ std::vsnprintf (message.text .data (), message.text .size (), fmt, arg);
273260
274- j += (int )strlen (tmp);
275-
276- ++i;
277-
278- break ;
279- }
280-
281- case ' i' : // decimal numbers
282- case ' d' :
283- {
284- char tmp[16 ];
285-
286- _itoa (va_arg (arg, int ), tmp, 10 );
287-
288- strcat (message, tmp);
261+ va_end (arg);
289262
290- j += ( int ) strlen (tmp);
263+ // output the message to the user program
291264
292- ++i;
265+ if (g_process_message.func ) {
266+ g_process_message.func (g_process_message.ctx , &message);
267+ }
268+ else {
269+ // legacy behaviour
293270
294- break ;
295- }
271+ if (freeimage_outputmessage_proc)
272+ freeimage_outputmessage_proc (message. scope , message. text . c_str ());
296273
297- case ' x' : // hexadecimal numbers
298- {
299- char tmp[16 ];
274+ if (freeimage_outputmessagestdcall_proc)
275+ freeimage_outputmessagestdcall_proc (message.scope , message.text .c_str ());
276+ }
277+ }
278+ }
300279
301- _itoa (va_arg (arg, int ), tmp, 16 );
302280
303- strcat (message, tmp);
281+ void FreeImage_SetProcessMessageFunction (void * new_ctx, FreeImage_ProcessMessageFunction new_func, void ** old_ctx, FreeImage_ProcessMessageFunction* old_func)
282+ {
283+ std::swap (g_process_message.ctx , new_ctx);
284+ std::swap (g_process_message.func , new_func);
285+ if (old_ctx) {
286+ *old_ctx = new_ctx;
287+ }
288+ if (old_func) {
289+ *old_func = new_func;
290+ }
291+ }
304292
305- j += (int )strlen (tmp);
306293
307- ++i;
294+ void FreeImage_ProcessMessage (const FIMESSAGE* msg)
295+ {
296+ if (!msg) {
297+ return ;
298+ }
308299
309- break ;
310- }
300+ if (g_process_message.func ) {
301+ g_process_message.func (g_process_message.ctx , msg);
302+ }
303+ }
311304
312- case ' s' : // strings
313- {
314- char *tmp = va_arg (arg, char *);
315305
316- strcat (message, tmp);
306+ FIMESSAGE* FreeImage_CreateMessage (FREE_IMAGE_FORMAT scope, FREE_IMAGE_SEVERITY severity, const char * what)
307+ {
308+ return new FIMESSAGE (scope, severity, what ? what : " Unknown" );
309+ }
317310
318- j += (int )strlen (tmp);
319311
320- ++i;
312+ void FreeImage_DeleteMessage (const FIMESSAGE* msg)
313+ {
314+ if (msg) {
315+ delete msg;
316+ }
317+ }
321318
322- break ;
323- }
324- };
325- } else {
326- message[j++] = fmt[i];
327- }
328- } else {
329- message[j++] = fmt[i];
330- };
331- }
332319
333- // deinitialize the optional parameter list
320+ FREE_IMAGE_FORMAT FreeImage_GetMessageScope (const FIMESSAGE* msg)
321+ {
322+ if (msg) {
323+ return msg->scope ;
324+ }
325+ return FIF_UNKNOWN;
326+ }
334327
335- va_end (arg);
336328
337- // output the message to the user program
329+ FREE_IMAGE_SEVERITY FreeImage_GetMessageSeverity (const FIMESSAGE* msg)
330+ {
331+ if (msg) {
332+ return msg->severity ;
333+ }
334+ return FISEV_NONE;
335+ }
338336
339- if (freeimage_outputmessage_proc)
340- freeimage_outputmessage_proc ((FREE_IMAGE_FORMAT)fif, message);
341337
342- if (freeimage_outputmessagestdcall_proc)
343- freeimage_outputmessagestdcall_proc ((FREE_IMAGE_FORMAT)fif, message);
338+ const char * FreeImage_GetMessageString (const FIMESSAGE* msg)
339+ {
340+ if (msg) {
341+ return msg->text .c_str ();
344342 }
343+ return " Unknown" ;
345344}
0 commit comments