2 # include "osx_messagebox.h"
13 #include "music_and_sound_g.h"
24 // For the printGLError macro
27 // Set to 0 when the game wants to quit
28 static int loopvar
= 1;
30 // Reports an error to the user, using a MessageBox and stderr.
31 void report_error(const char *error_preface
, const char *error_message
)
34 // +4 = +colon +space +newline +nul
35 buf
= new char[strlen(error_preface
) + strlen(error_message
) + 4];
36 sprintf(buf
, "%s: %s\n", error_preface
, error_message
);
37 MessageBox(NULL
, buf
, "Error", MB_OK
);
38 fprintf(stderr
, "%s", buf
);
42 Either
<texture_fullid
,texture_ttfid
> renderer::screen_to_texid(int x
, int y
) {
43 const int tile
= x
* gps
.dimy
+ y
;
44 const unsigned char *s
= screen
+ tile
*4;
46 struct texture_fullid ret
;
52 // TTF text does not get the full treatment.
53 if (s
[3] == GRAPHICSTYPE_TTF
) {
54 texture_ttfid texpos
= *((unsigned int *)s
) & 0xffffff;
55 return Either
<texture_fullid
,texture_ttfid
>(texpos
);
56 } else if (s
[3] == GRAPHICSTYPE_TTFCONT
) {
57 // TTFCONT means this is a tile that does not have TTF anchored on it, but is covered by TTF.
58 // Since this may actually be stale information, we'll draw it as a blank space,
62 // Otherwise, it's a normal (graphical?) tile.
64 bold
= (s
[3] != 0) * 8;
65 fg
= (s
[1] + bold
) % 16;
69 static bool use_graphics
= init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_USE_GRAPHICS
);
72 const long texpos
= screentexpos
[tile
];
73 const char addcolor
= screentexpos_addcolor
[tile
];
74 const unsigned char grayscale
= screentexpos_grayscale
[tile
];
75 const unsigned char cf
= screentexpos_cf
[tile
];
76 const unsigned char cbr
= screentexpos_cbr
[tile
];
81 ret
.r
= enabler
.ccolor
[cf
][0];
82 ret
.g
= enabler
.ccolor
[cf
][1];
83 ret
.b
= enabler
.ccolor
[cf
][2];
84 ret
.br
= enabler
.ccolor
[cbr
][0];
85 ret
.bg
= enabler
.ccolor
[cbr
][1];
86 ret
.bb
= enabler
.ccolor
[cbr
][2];
87 } else if (addcolor
) {
90 ret
.r
= ret
.g
= ret
.b
= 1;
91 ret
.br
= ret
.bg
= ret
.bb
= 0;
97 ret
.texpos
= enabler
.is_fullscreen() ?
98 init
.font
.large_font_texpos
[ch
] :
99 init
.font
.small_font_texpos
[ch
];
101 ret
.r
= enabler
.ccolor
[fg
][0];
102 ret
.g
= enabler
.ccolor
[fg
][1];
103 ret
.b
= enabler
.ccolor
[fg
][2];
104 ret
.br
= enabler
.ccolor
[bg
][0];
105 ret
.bg
= enabler
.ccolor
[bg
][1];
106 ret
.bb
= enabler
.ccolor
[bg
][2];
110 return Either
<texture_fullid
,texture_ttfid
>(ret
);
115 # include "renderer_curses.cpp"
117 #include "renderer_2d.hpp"
118 #include "renderer_opengl.hpp"
121 enablerst::enablerst() {
125 calculated_fps
= calculated_gfps
= frame_sum
= gframe_sum
= frame_last
= gframe_last
= 0;
126 fps
= 100; gfps
= 20;
127 fps_per_gfps
= fps
/ gfps
;
131 void renderer::display()
133 const int dimx
= init
.display
.grid_x
;
134 const int dimy
= init
.display
.grid_y
;
135 static bool use_graphics
= init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_USE_GRAPHICS
);
136 if (gps
.force_full_display_count
) {
137 // Update the entire screen
140 Uint32
*screenp
= (Uint32
*)screen
, *oldp
= (Uint32
*)screen_old
;
143 for (int x2
=0; x2
< dimx
; x2
++) {
144 for (int y2
=0; y2
< dimy
; y2
++, ++off
, ++screenp
, ++oldp
) {
145 // We don't use pointers for the non-screen arrays because we mostly fail at the
146 // *first* comparison, and having pointers for the others would exceed register
148 // Partial printing (and color-conversion): Big-ass if.
149 if (*screenp
== *oldp
&&
150 screentexpos
[off
] == screentexpos_old
[off
] &&
151 screentexpos_addcolor
[off
] == screentexpos_addcolor_old
[off
] &&
152 screentexpos_grayscale
[off
] == screentexpos_grayscale_old
[off
] &&
153 screentexpos_cf
[off
] == screentexpos_cf_old
[off
] &&
154 screentexpos_cbr
[off
] == screentexpos_cbr_old
[off
])
156 // Nothing's changed, this clause deliberately empty
163 for (int x2
=0; x2
< dimx
; ++x2
) {
164 for (int y2
=0; y2
< dimy
; ++y2
, ++screenp
, ++oldp
) {
165 if (*screenp
!= *oldp
) {
172 if (gps
.force_full_display_count
> 0) gps
.force_full_display_count
--;
175 void renderer::cleanup_arrays() {
176 if (screen
) delete[] screen
;
177 if (screentexpos
) delete[] screentexpos
;
178 if (screentexpos_addcolor
) delete[] screentexpos_addcolor
;
179 if (screentexpos_grayscale
) delete[] screentexpos_grayscale
;
180 if (screentexpos_cf
) delete[] screentexpos_cf
;
181 if (screentexpos_cbr
) delete[] screentexpos_cbr
;
182 if (screen_old
) delete[] screen_old
;
183 if (screentexpos_old
) delete[] screentexpos_old
;
184 if (screentexpos_addcolor_old
) delete[] screentexpos_addcolor_old
;
185 if (screentexpos_grayscale_old
) delete[] screentexpos_grayscale_old
;
186 if (screentexpos_cf_old
) delete[] screentexpos_cf_old
;
187 if (screentexpos_cbr_old
) delete[] screentexpos_cbr_old
;
190 void renderer::gps_allocate(int x
, int y
) {
193 gps
.screen
= screen
= new unsigned char[x
*y
*4];
194 memset(screen
, 0, x
*y
*4);
195 gps
.screentexpos
= screentexpos
= new long[x
*y
];
196 memset(screentexpos
, 0, x
*y
*sizeof(long));
197 gps
.screentexpos_addcolor
= screentexpos_addcolor
= new char[x
*y
];
198 memset(screentexpos_addcolor
, 0, x
*y
);
199 gps
.screentexpos_grayscale
= screentexpos_grayscale
= new unsigned char[x
*y
];
200 memset(screentexpos_grayscale
, 0, x
*y
);
201 gps
.screentexpos_cf
= screentexpos_cf
= new unsigned char[x
*y
];
202 memset(screentexpos_cf
, 0, x
*y
);
203 gps
.screentexpos_cbr
= screentexpos_cbr
= new unsigned char[x
*y
];
204 memset(screentexpos_cbr
, 0, x
*y
);
206 screen_old
= new unsigned char[x
*y
*4];
207 memset(screen_old
, 0, x
*y
*4);
208 screentexpos_old
= new long[x
*y
];
209 memset(screentexpos_old
, 0, x
*y
*sizeof(long));
210 screentexpos_addcolor_old
= new char[x
*y
];
211 memset(screentexpos_addcolor_old
, 0, x
*y
);
212 screentexpos_grayscale_old
= new unsigned char[x
*y
];
213 memset(screentexpos_grayscale_old
, 0, x
*y
);
214 screentexpos_cf_old
= new unsigned char[x
*y
];
215 memset(screentexpos_cf_old
, 0, x
*y
);
216 screentexpos_cbr_old
= new unsigned char[x
*y
];
217 memset(screentexpos_cbr_old
, 0, x
*y
);
222 void renderer::swap_arrays() {
223 screen
= screen_old
; screen_old
= gps
.screen
; gps
.screen
= screen
;
224 screentexpos
= screentexpos_old
; screentexpos_old
= gps
.screentexpos
; gps
.screentexpos
= screentexpos
;
225 screentexpos_addcolor
= screentexpos_addcolor_old
; screentexpos_addcolor_old
= gps
.screentexpos_addcolor
; gps
.screentexpos_addcolor
= screentexpos_addcolor
;
226 screentexpos_grayscale
= screentexpos_grayscale_old
; screentexpos_grayscale_old
= gps
.screentexpos_grayscale
; gps
.screentexpos_grayscale
= screentexpos_grayscale
;
227 screentexpos_cf
= screentexpos_cf_old
; screentexpos_cf_old
= gps
.screentexpos_cf
; gps
.screentexpos_cf
= screentexpos_cf
;
228 screentexpos_cbr
= screentexpos_cbr_old
; screentexpos_cbr_old
= gps
.screentexpos_cbr
; gps
.screentexpos_cbr
= screentexpos_cbr
;
230 gps
.screen_limit
= gps
.screen
+ gps
.dimx
* gps
.dimy
* 4;
233 void enablerst::pause_async_loop() {
234 struct async_cmd cmd
;
235 cmd
.cmd
= async_cmd::pause
;
236 async_tobox
.write(cmd
);
240 // Wait until the previous command has been acknowledged, /or/
241 // async_loop has quit. Incidentally execute any requests in the
243 void enablerst::async_wait() {
244 if (loopvar
== 0) return;
246 bool reset_textures
= false;
248 async_frombox
.read(r
);
250 case async_msg::quit
:
253 case async_msg::complete
:
254 if (reset_textures
) {
255 puts("Resetting textures");
256 textures
.remove_uploaded_textures();
257 textures
.upload_textures();
260 case async_msg::set_fps
:
262 async_fromcomplete
.write();
264 case async_msg::set_gfps
:
266 async_fromcomplete
.write();
268 case async_msg::push_resize
:
269 override_grid_size(r
.x
, r
.y
);
270 async_fromcomplete
.write();
272 case async_msg::pop_resize
:
274 async_fromcomplete
.write();
276 case async_msg::reset_textures
:
277 reset_textures
= true;
280 puts("EMERGENCY: Unknown case in async_wait");
286 void enablerst::async_loop() {
287 async_paused
= false;
289 int total_frames
= 0;
290 int fps
= 100; // Just a thread-local copy
292 // cout << "FRAMES: " << frames << endl;
293 // Check for commands
295 bool have_cmd
= true;
297 if (async_paused
|| (async_frames
== 0 && !(enabler
.flag
& ENABLERFLAG_MAXFPS
)))
298 async_tobox
.read(cmd
);
300 have_cmd
= async_tobox
.try_read(cmd
);
301 // Obey the command, would you kindly.
304 case async_cmd::pause
:
307 async_frombox
.write(async_msg(async_msg::complete
));
309 case async_cmd::start
:
310 async_paused
= false;
314 case async_cmd::render
:
315 if (flag
& ENABLERFLAG_RENDER
) {
317 renderer
->swap_arrays();
318 if (total_frames
% 1800 == 0)
321 flag
&= ~ENABLERFLAG_RENDER
;
324 async_frombox
.write(async_msg(async_msg::complete
));
327 async_frames
+= cmd
.val
;
328 if (async_frames
> fps
*3) async_frames
= fps
*3; // Just in case
330 case async_cmd::set_fps
:
336 // Run the main-loop, maybe
337 if (!async_paused
&& (async_frames
|| (enabler
.flag
& ENABLERFLAG_MAXFPS
))) {
339 async_frombox
.write(async_msg(async_msg::quit
));
340 return; // We're done.
346 if (async_frames
< 0) async_frames
= 0;
349 SDL_NumJoysticks(); // Hook for dfhack
353 void enablerst::do_frame() {
354 // Check how long it's been, exactly
355 const Uint32 now
= SDL_GetTicks();
356 const Uint32 interval
= CLAMP(now
- last_tick
, 0, 1000); // Anything above a second doesn't count
357 // cout << last_tick << " + " << interval << " = " << now << endl;
360 // Update outstanding-frame counts
361 outstanding_frames
+= interval
* fps
/ 1000;
362 outstanding_gframes
+= interval
* gfps
/ 1000;
363 if (outstanding_gframes
> 3) {
364 outstanding_gframes
= 3;
366 // cout << outstanding_frames << " " << outstanding_gframes << endl;
368 // Update the loop's tick-counter suitably
369 if (outstanding_frames
>= 1) {
370 async_cmd
cmd(async_cmd::inc
);
371 cmd
.val
= outstanding_frames
;
372 outstanding_frames
-= cmd
.val
;
373 async_tobox
.write(cmd
);
376 // Store the current time, for things that are fine with approximations
377 enabler
.clock
= SDL_GetTicks();
379 // If it's time to render..
380 if (outstanding_gframes
>= 1 &&
381 (!sync
|| glClientWaitSync(sync
, 0, 0) == GL_ALREADY_SIGNALED
)) {
382 // Get the async-loop to render_things
383 async_cmd
cmd(async_cmd::render
);
384 async_tobox
.write(cmd
);
392 outstanding_gframes
--;
395 // Sleep until the next gframe
396 if (outstanding_gframes
< 1) {
397 float fragment
= 1 - outstanding_gframes
;
398 float milliseconds
= fragment
/ gfps
* 1000;
399 // cout << milliseconds << endl;
400 SDL_Delay(milliseconds
);
404 void enablerst::eventLoop_SDL()
408 const SDL_Surface
*screen
= SDL_GetVideoSurface();
409 Uint32 mouse_lastused
= 0;
410 SDL_ShowCursor(SDL_DISABLE
);
412 // Initialize the grid
413 renderer
->resize(screen
->w
, screen
->h
);
416 Uint32 now
= SDL_GetTicks();
417 bool paused_loop
= false;
419 // Check for zoom commands
421 while (async_zoom
.try_read(zoom
)) {
422 if (overridden_grid_sizes
.size())
423 continue; // No zooming in movies
428 if (zoom
== zoom_fullscreen
)
429 renderer
->set_fullscreen();
431 renderer
->zoom(zoom
);
434 // Check for SDL events
435 while (SDL_PollEvent(&event
)) {
436 // Make sure mainloop isn't running while we're processing input
442 switch (event
.type
) {
444 // Disable mouse if it's been long enough
445 if (mouse_lastused
+ 5000 < now
) {
446 if(init
.input
.flag
.has_flag(INIT_INPUT_FLAG_MOUSE_PICTURE
)) {
447 // hide the mouse picture
448 // enabler.set_tile(0, TEXTURE_MOUSE, enabler.mouse_x, enabler.mouse_y);
450 SDL_ShowCursor(SDL_DISABLE
);
454 enabler
.add_input(event
, now
);
456 case SDL_MOUSEBUTTONDOWN
:
457 case SDL_MOUSEBUTTONUP
:
458 if (!init
.input
.flag
.has_flag(INIT_INPUT_FLAG_MOUSE_OFF
)) {
459 int isdown
= (event
.type
== SDL_MOUSEBUTTONDOWN
);
460 if (event
.button
.button
== SDL_BUTTON_LEFT
) {
461 enabler
.mouse_lbut
= isdown
;
462 enabler
.mouse_lbut_down
= isdown
;
464 enabler
.mouse_lbut_lift
= 0;
465 } else if (event
.button
.button
== SDL_BUTTON_RIGHT
) {
466 enabler
.mouse_rbut
= isdown
;
467 enabler
.mouse_rbut_down
= isdown
;
469 enabler
.mouse_rbut_lift
= 0;
471 enabler
.add_input(event
, now
);
474 case SDL_MOUSEMOTION
:
475 // Deal with the mouse hiding bit
476 mouse_lastused
= now
;
477 if(init
.input
.flag
.has_flag(INIT_INPUT_FLAG_MOUSE_PICTURE
)) {
478 // turn on mouse picture
479 // enabler.set_tile(gps.tex_pos[TEXTURE_MOUSE], TEXTURE_MOUSE,enabler.mouse_x, enabler.mouse_y);
481 SDL_ShowCursor(SDL_ENABLE
);
484 case SDL_ACTIVEEVENT
:
485 enabler
.clear_input();
486 if (event
.active
.state
& SDL_APPACTIVE
) {
487 if (event
.active
.gain
) {
488 enabler
.flag
|=ENABLERFLAG_RENDER
;
489 gps
.force_full_display_count
++;
493 case SDL_VIDEOEXPOSE
:
494 gps
.force_full_display_count
++;
495 enabler
.flag
|=ENABLERFLAG_RENDER
;
497 case SDL_VIDEORESIZE
:
498 if (is_fullscreen());
499 //errorlog << "Caught resize event in fullscreen??\n";
501 //gamelog << "Resizing window to " << event.resize.w << "x" << event.resize.h << endl << flush;
502 renderer
->resize(event
.resize
.w
, event
.resize
.h
);
505 } // switch (event.type)
508 // Update mouse state
509 if (!init
.input
.flag
.has_flag(INIT_INPUT_FLAG_MOUSE_OFF
)) {
510 int mouse_x
= -1, mouse_y
= -1, mouse_state
;
511 // Check whether the renderer considers this valid input or not, and write it to gps
512 if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS
) &&
513 renderer
->get_mouse_coords(mouse_x
, mouse_y
)) {
518 if (mouse_x
!= gps
.mouse_x
|| mouse_y
!= gps
.mouse_y
||
519 mouse_state
!= enabler
.tracking_on
) {
520 // Pause rendering loop and update values
525 enabler
.tracking_on
= mouse_state
;
526 gps
.mouse_x
= mouse_x
;
527 gps
.mouse_y
= mouse_y
;
532 unpause_async_loop();
535 #if !defined(NO_FMOD)
536 // Call FMOD::System.update(). Manages a bunch of sound stuff.
542 int enablerst::loop(string cmdline
) {
543 command_line
= cmdline
;
545 // Initialize the tick counters
549 // Call DF's initialization routine
553 // Allocate a renderer
554 if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_TEXT
)) {
556 renderer
= new renderer_curses();
558 report_error("PRINT_MODE", "TEXT not supported on windows");
561 } else if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_2D
)) {
562 renderer
= new renderer_2d();
563 } else if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_ACCUM_BUFFER
)) {
564 renderer
= new renderer_accum_buffer();
565 } else if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_FRAME_BUFFER
)) {
566 renderer
= new renderer_framebuffer();
567 } else if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_PARTIAL_PRINT
)) {
568 if (init
.display
.partial_print_count
)
569 renderer
= new renderer_partial();
571 renderer
= new renderer_once();
572 } else if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_VBO
)) {
573 renderer
= new renderer_vbo();
575 renderer
= new renderer_opengl();
578 // At this point we should have a window that is setup to render DF.
579 if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_TEXT
)) {
584 SDL_EnableUNICODE(1);
590 // Clean up graphical resources
594 void enablerst::override_grid_size(int x
, int y
) {
595 if (SDL_ThreadID() != renderer_threadid
) {
596 // Ask the renderer to do it
597 async_msg
m(async_msg::push_resize
);
599 async_frombox
.write(m
);
600 async_fromcomplete
.read();
602 // We are the renderer; do it.
603 overridden_grid_sizes
.push(make_pair(init
.display
.grid_x
,init
.display
.grid_y
));
604 renderer
->grid_resize(x
, y
);
608 void enablerst::release_grid_size() {
609 if (SDL_ThreadID() != renderer_threadid
) {
610 async_frombox
.write(async_msg(async_msg::pop_resize
));
611 async_fromcomplete
.read();
613 if (!overridden_grid_sizes
.size()) return;
614 // FIXME: Find out whatever is causing release to be called too rarely; right now
615 // we're overriding once per movie but apparently only releasing for the last one.
617 while (overridden_grid_sizes
.size()) {
618 sz
= overridden_grid_sizes
.top();
619 overridden_grid_sizes
.pop();
621 zoom_display(zoom_resetgrid
);
625 void enablerst::zoom_display(zoom_commands command
) {
626 async_zoom
.write(command
);
629 int enablerst::calculate_fps() {
630 if (frame_timings
.size() < 50)
633 return calculated_fps
;
635 int enablerst::calculate_gfps() {
636 if (gframe_timings
.size() < 50)
639 return calculated_gfps
;
642 void enablerst::do_update_fps(queue
<int> &q
, int &sum
, int &last
, int &calc
) {
643 while (q
.size() > 50 && sum
> 10000) {
647 const int now
= SDL_GetTicks();
648 const int interval
= now
- last
;
653 calc
= q
.size() * 1000 / sum
;
656 void enablerst::clear_fps() {
657 while (frame_timings
.size())
660 frame_last
= SDL_GetTicks();
661 calculated_fps
= get_fps();
664 void enablerst::update_fps() {
665 do_update_fps(frame_timings
, frame_sum
, frame_last
, calculated_fps
);
668 void enablerst::update_gfps() {
669 do_update_fps(gframe_timings
, gframe_sum
, gframe_last
, calculated_gfps
);
672 void enablerst::set_fps(int fps
) {
673 if (SDL_ThreadID() != renderer_threadid
) {
674 async_msg
m(async_msg::set_fps
);
677 async_frombox
.write(m
);
678 async_fromcomplete
.read();
683 fps_per_gfps
= fps
/ gfps
;
684 struct async_cmd cmd
;
685 cmd
.cmd
= async_cmd::set_fps
;
687 async_tobox
.write(cmd
);
688 async_tobox
.write(async_cmd(async_cmd::start
));
692 void enablerst::set_gfps(int gfps
) {
693 if (SDL_ThreadID() != renderer_threadid
) {
694 async_msg
m(async_msg::set_gfps
);
696 async_frombox
.write(m
);
697 async_fromcomplete
.read();
702 fps_per_gfps
= fps
/ gfps
;
706 int call_loop(void *dummy
) {
707 enabler
.async_loop();
711 int main (int argc
, char* argv
[]) {
713 setlocale(LC_ALL
, "");
715 #if !defined(__APPLE__) && defined(unix)
717 if (getenv("DISPLAY"))
718 gtk_ok
= gtk_init_check(&argc
, &argv
);
721 // Initialise minimal SDL subsystems.
722 int retval
= SDL_Init(SDL_INIT_TIMER
);
725 report_error("SDL initialization failure", SDL_GetError());
728 enabler
.renderer_threadid
= SDL_ThreadID();
730 // Spawn simulation thread
731 SDL_CreateThread(call_loop
, NULL
);
733 init
.begin(); // Load init.txt settings
735 #if !defined(__APPLE__) && defined(unix)
736 if (!gtk_ok
&& !init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_TEXT
)) {
737 puts("Display not found and PRINT_MODE not set to TEXT, aborting.");
740 if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_TEXT
) &&
741 init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_USE_GRAPHICS
)) {
742 puts("Graphical tiles are not compatible with text output, sorry");
747 // Initialize video, if we /use/ video
748 retval
= SDL_InitSubSystem(init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_TEXT
) ? 0 : SDL_INIT_VIDEO
);
750 report_error("SDL initialization failure", SDL_GetError());
755 if (!init
.media
.flag
.has_flag(INIT_MEDIA_FLAG_SOUND_OFF
)) {
757 if (!musicsound
.initsound()) {
758 puts("Initializing OpenAL failed, no sound will be played");
759 init
.media
.flag
.add_flag(INIT_MEDIA_FLAG_SOUND_OFF
);
765 // Attempt to get as good a timer as possible
767 while (timeBeginPeriod(ms
) != TIMERR_NOERROR
) ms
++;
772 enabler
.load_keybindings("data/init/interface.txt");
775 for (int i
= 1; i
< argc
; ++i
) {
776 char *option
= argv
[i
];
780 //main removes quotes, unlike the winmain version, so it has to be rebuilt
795 int result
= enabler
.loop(cmdLine
);
806 char get_slot_and_addbit_uchar(unsigned char &addbit
,long &slot
,long checkflag
,long slotnum
)
808 if(checkflag
<0)return 0;
812 if(slot
>=slotnum
)return 0;
814 //FIND PROPER BIT IN THAT SLOT
815 addbit
=1<<(checkflag
%8);
820 void text_system_file_infost::initialize_info()
822 std::ifstream
fseed(filename
.c_str());
827 while(std::getline(fseed
,str
))
829 if(str
.length()>0)number
++;
835 str
="Error Initializing Text: ";
837 errorlog_string(str
);
842 void text_system_file_infost::get_text(text_infost
&text
)
848 std::ifstream
fseed(filename
.c_str());
853 int num
=trandom(number
);
855 //SKIP AHEAD TO THE RIGHT SPOT
858 std::getline(fseed
,str
);
862 //PROCESS THE STRING INTO TEXT ELEMENTS
863 if(std::getline(fseed
,str
))
869 text_info_elementst
*newel
;
870 long end
=str
.length();
874 if(isspace(str
[end
-1]))end
--;
880 for(curpos
=0;curpos
<end
;curpos
++)
882 //HANDLE TOKEN OR ENDING
883 //TWO FILE TOKENS IN A ROW MEANS LONG
885 if(str
[curpos
]==file_token
|| curpos
==end
-1)
887 if(str
[curpos
]!=file_token
)nextstr
+=str
[curpos
];
889 //HAVE SOMETHING == SAVE IT
894 newel
=new text_info_element_longst(atoi(nextstr
.c_str()));
895 text
.element
.push_back(newel
);
900 newel
=new text_info_element_stringst(nextstr
);
901 text
.element
.push_back(newel
);
912 //JUST ADD IN ANYTHING ELSE
915 nextstr
+=str
[curpos
];
923 void curses_text_boxst::add_paragraph(const string
&src
,int32_t para_width
)
927 add_paragraph(sp
,para_width
);
930 void curses_text_boxst::add_paragraph(stringvectst
&src
,int32_t para_width
)
932 bool skip_leading_spaces
=false;
934 //ADD EACH OF THE STRINGS ON IN TURN
938 for(s
=0;s
<src
.str
.size();s
++)
940 //GRAB EACH WORD, AND SEE IF IT FITS, IF NOT START A NEW LINE
941 for(pos
=0;pos
<src
.str
[s
]->dat
.size();pos
++)
943 if(skip_leading_spaces
)
945 if(src
.str
[s
]->dat
[pos
]==' ')continue;
946 else skip_leading_spaces
=false;
950 curstr
+=src
.str
[s
]->dat
[pos
];
952 //IF TOO LONG, CUT BACK TO FIRST SPACE
953 if(curstr
.length()>para_width
)
962 }while(src
.str
[s
]->dat
[pos
]!=' '&&pos
>0);
964 //IF WENT ALL THE WAY BACK, INTRODUCE A SPACE
965 if(minus
==curstr
.size())
967 src
.str
[s
]->dat
.insert(opos
-1," ");
971 curstr
.resize(curstr
.size()-minus
);
972 text
.add_string(curstr
);
973 skip_leading_spaces
=true;
981 if(!curstr
.empty())text
.add_string(curstr
);